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

问题描述

我想知道清漆和标题 vmod 的意外行为。 以下 vcl 将无法编译,因为在 header.copy 中使用了 vcl_deliver

为什么这里不允许使用 header.copy?有没有关于这种行为的文件?清漆和标题的文档都没有说明它。

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

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]:错误:Feb 09 06:40:11
epcentos7.dev varnishd[12938]:来自 VCC 编译器的消息:2 月 9 日
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); 2 月 9 日 06:40:11 epcentos7.dev
清漆[12938]:
--------------######------------------------------ --------------
Feb 09 06:40:11 epcentos7.dev varnishd[12938]:在子程序中不可用
'vcl_deliver'。 Feb 09 06:40:11 epcentos7.dev varnishd[12938]:运行
VCC 编译器失败,退出时间为 2 Feb 09 06:40:11 epcentos7.dev
varnishd[12938]:VCL 编译失败 2 月 9 日 06:40:11 epcentos7.dev
systemd[1]:varnish.service:控制进程退出代码=退出
status=255 Feb 09 06:40:11 epcentos7.dev systemd[1]:启动失败
Varnish Cache,一种高性能的 HTTP 加速器。

解决方法

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 对象中,该对象用于向请求它的客户端提供响应。