为什么header.copy不能用在vcl_deliver中?

Why can header.copy not be used in vcl_deliver?

我想知道 varnish 和 header vmod 的意外行为。 下面的vcl编译不了,因为在vcl_deliver.

中使用了header.copy

为什么这里不允许使用header.copy?这种行为有任何文件吗? varnish 的文档和 header 都没有说明任何事情。

我不需要解决方法。我已经有了。

vcl 4.1;

import header;
backend default {
    .host = "127.0.0.1";
    .port = "8888";
}

sub vcl_backend_response {
  header.copy(beresp.http.Set-Cookie, beresp.http.X-Set-Cookie);
  unset beresp.http.Set-Cookie;
}

sub vcl_deliver {
  header.copy(beresp.http.X-Set-Cookie, beresp.http.Set-Cookie);
  unset beresp.http.X-Set-Cookie;
}

编译时会出现如下错误

Feb 09 06:40:11 epcentos7.dev varnishd[12938]: Error: Feb 09 06:40:11
epcentos7.dev varnishd[12938]: Message from VCC-compiler: Feb 09
06:40:11 epcentos7.dev varnishd[12938]: ('/etc/varnish/default.vcl'
Line 15 Pos 15) -- (Pos 20) Feb 09 06:40:11 epcentos7.dev
varnishd[12938]: header.copy(beresp.http.X-Set-Cookie,
beresp.http.Set-Cookie); Feb 09 06:40:11 epcentos7.dev
varnishd[12938]:
--------------######--------------------------------------------
Feb 09 06:40:11 epcentos7.dev varnishd[12938]: Not available in subroutine
'vcl_deliver'. Feb 09 06:40:11 epcentos7.dev varnishd[12938]: Running
VCC-compiler failed, exited with 2 Feb 09 06:40:11 epcentos7.dev
varnishd[12938]: VCL compilation failed Feb 09 06:40:11 epcentos7.dev
systemd[1]: varnish.service: control process exited, code=exited
status=255 Feb 09 06:40:11 epcentos7.dev systemd[1]: Failed to start
Varnish Cache, a high-performance HTTP accelerator.

beresp 对象在 vcl_deliver 中不可用,因为它是不同流程的一部分。等效项是 resp,这将导致以下 header.copy() 行:

sub vcl_deliver {
  header.copy(resp.http.X-Set-Cookie, resp.http.Set-Cookie);
  unset resp.http.X-Set-Cookie;
}

交易范围

Varnish 有两种事务:

  • 客户端事务:从客户端接收请求,并向客户端提供响应
  • 后端事务:后端请求发送到后端,后端响应从后端接收

当请求导致 缓存命中 时,Varnish 只需要一个 客户端事务 来处理它。未建立与后端的连接,因此未使用 后端事务

当请求导致缓存未命中时,Varnish 将使用客户端事务与客户端交互,并使用后端事务从后端获取非缓存数据

子程序范围

考虑到 事务范围,我们现在可以将 VCL 子例程映射到它。

以下是客户端子例程的概述:

  • vcl_recv
  • vcl_hash
  • vcl_miss
  • vcl_hit
  • vcl_pass
  • vcl_deliver
  • vcl_synth
  • vcl_purge

这些事务可以访问 req 对象和 resp 对象以进行请求和响应。

还有后台子程序如:

  • vcl_backend_fetch
  • vcl_backend_response
  • vcl_backend_error

这些子例程可以访问 bereqberesp 对象。

对象流

收到请求后,请求信息存储在req对象中。当请求导致 缓存未命中 时,req 对象信息被复制到 bereq 对象中。

当后端响应时,beresp 对象包含(可能)可缓存的信息。 beresp 对象数据被复制到代表缓存中存储内容的 obj 对象中,同时也被复制到 resp 对象中,该对象用于为请求它的客户端提供响应。