Varnish 5.1中的更改

我们在Varnish 5.1中有几个有趣的新功能,我们有很多小的改进和错误修复,自从Varnish 5.0以来,我们总共提交了大约750次,所以这只是其中的一些亮点。

Varnish 5.1中最大的变化可能是Varnish的几个非常重要的贡献者已经换了工作,因此不再是Varnish项目的积极贡献者。

佩尔·布尔是第一批意识到瓦尼什不仅仅是几家北欧报纸的节目的人之一,他创办了瓦尼什软件公司,这是瓦尼什项目的主要赞助商之一。

Lasse Karstensen被PER捆绑到Varnish Software,除了他的其他职责外,我们现在工作的11年中的大部分时间里,他都负责项目的系统管理和发布工程。

Per&Lasse:谢谢还不够,我们祝你未来一切顺利!

启动CLI命令文件

在varnishd中添加新的‘-i cli_file’选项将使使用Varnish 5.0中引入的VCL标签更加实用。

文件中的CLI命令将在工作进程启动之前执行,因此它可能包含::

vcl.load panic /etc/varnish_panic.vcl
vcl.load siteA0 /etc/varnish_siteA.vcl
vcl.load siteB0 /etc/varnish_siteB.vcl
vcl.load siteC0 /etc/varnish_siteC.vcl
vcl.label siteA siteA0
vcl.label siteB siteB0
vcl.label siteC siteC0
vcl.load main /etc/varnish_main.vcl
vcl.use main

如果文件中的命令以‘-’为前缀,则失败不会中止启动。

与此更改相关的是,我们对参数检查进行了重新排序,以便更一致地报告参数问题。

如果您还没有听说过它们,标记VCL程序允许您扩展到Main::VCL_recv{}中的其他VCL,在上面的示例中它可能类似于::

sub vcl_recv {
    if (req.http.host ~ "asite.example.com$") {
        return(vcl(siteA));
    }
    if (req.http.host ~ "bsite.example.com$") {
        return(vcl(siteB));
    }
    if (req.http.host ~ "csite.example.com$") {
        return(vcl(siteC));
    }
    // Main site processing ...
}

通用VCL返回(失败)

现在有可能 return(fail) 在VCL的任何地方,包括VMOD内部。这将导致VCL处理立即终止。

除了……之外 return(fail) ,此机制将用于处理所有故障情况,而无需安全的回退,例如工作空间耗尽、头文件过多等。(这是一项正在进行的工作,在我们完成之前有很多代码需要检查。)

在……里面 vcl_init{} 失败会导致 vcl.load 失败了,这对这个子例程来说并不新鲜。

任何客户端VCL方法出现故障 (vcl_recv{}vcl_hash{} .) except vcl_synth{} ,将请求发送到 vcl_synth{} 带503,原因是“VCL失败”。

后端出现故障 (vcl_backend_*{} )会导致提取失败。

(VMOD编写器应使用新的 VRT_fail(ctx, format_string, ...) 记录SLT_VCL_ERROR记录的函数。)

支持HTTP/2的进展

Http/2支持比5.0更好,在我们自己的Varnish-cache.org网站上现在已经启用并很好地存活了下来,但仍然缺少一些东西,最明显的是Windows和优先级,这可能会对更复杂的网站造成致命的影响。

我们希望在2017年秋季发布的Varnish-缓存中提供对HTTP/2的支持,但这需要测试和来自实际应用程序的反馈。

因此,如果您有机会测试我们的HTTP/2代码,请务必这样做,如果有任何崩溃、错误或其他问题,请向我们报告。

要启用HTTP/2,您需要 param.set feature +http2 但由于网络政治的原因,如果你在Varnish前面有一个用ALPN通告HTTP2的SSL代理,你将只能看到HTTP/2流量。

对于Hitch SSL代理,添加参数 --alpn-protos="h2,http/1.1"

击球传球又回来了

如中所暗示的 Varnish 5.0中的更改 ,我们恢复了调用VCL中旧的一击即传功能的可能性。对无法缓存的内容的处理仍然是默认的,这是5.0版中的新功能,我们称之为“命中未命中”。现在你可以选择击球传球 return(pass(DURATION)) 从… vcl_backend_response ,将参数中的命中传球状态的持续时间设置为 pass 。例如: return(pass(120s))

简单地说:当 beresp.uncacheable 设置为 true 在……里面 vcl_backend_response ,Varnish使用缓存中的最小对象将其记下来,并在下一次查找同一对象时再次找到该信息。本质上,缓存用于记住上一个后端响应是不可缓存的。在这种情况下,Varnish将继续执行缓存未命中操作,因此响应可能会在后续请求中变为可缓存。不同之处在于,当响应被标记为不可缓存时,Varnish不会像对普通未命中那样执行请求合并。对于普通的未命中,当同时存在针对同一对象的待决请求时,一次只执行一个获取,因为响应可能被缓存,在这种情况下,缓存的响应可能用于剩余的请求。但这不适用于“命中未命中”对象,因为已知它们在上一次提取时是不可缓存的。

builtin.vcl 集合 beresp.uncacheabletrue 当后端响应满足指示不应缓存它的多个条件时,例如,如果TTL已被确定为0(可能是由于 Cache-Control 标头),或者如果 Set-Cookie 响应中存在标头。因此,命中未命中是不可缓存的后端响应的默认设置。

这样做的一个后果是,在默认情况下,对不可缓存响应的提取不能是有条件的。也就是说,后端请求可能不包括报头 If-Modified-SinceIf-None-Match ,这可能会导致后端返回没有响应正文的状态“304 Not Modify”。由于对缓存未命中的响应可能会被缓存,因此必须有一个正文来缓存,对于命中未命中也是如此。如果客户端请求中存在这两个标头中的任何一个,则会将它们从后端请求中删除,以表示未命中或命中未命中。

由于有条件的后端请求和304响应可能对不可缓存内容的性能至关重要,特别是在响应正文很大的情况下,我们再次提供了旧的一击即传功能, return(pass(DURATION)) 在VCL。

与命中未命中一样,Varnish使用缓存来记录命中传递对象,并在随后的查找中再次找到它们。然后,将像处理普通通行证一样处理这些申请 (return(pass) 从… vcl_recv )--没有请求合并,响应也不会被缓存,即使它本来可能是缓存的。 If-Modified-SinceIf-None-Match 客户端请求中的头部在后端请求中被传递,并且具有状态304且没有正文的后端响应被传递回客户端。

对象的命中传球状态持续给定的时间,该时间是从 vcl_backend_response 。在“一击即传TTL”过去之后,下一个请求将是一个普通的未命中。因此,在经过该时间之前,命中传球对象不能再次变为可缓存对象。

304通过后未修改响应

与前一个主题相关的是,Varnish处理一个非常具体的案例的方式发生了变化:决定是否在通过后向客户端发送“304 Not Modify”响应,此时后端有机会发送304响应,但选择不发送200响应状态。

以前,当发生这种情况时,Varnish会与后端一起发送200响应和响应正文给客户端。即使后端设置了响应头,情况也是如此 ETag 和/或 Last-Modified 因此,当与请求标头相比时 If-None-MatchIf-Modified-Since ,304的回应似乎是有必要的。由于这些标头被传递回客户端,因此从客户端的角度来看,结果可能看起来有点奇怪--客户端使用请求标头来询问响应是否未修改,而响应标头似乎表明它没有修改,但响应状态表明它是未修改的。

现在,只在交付时根据客户端请求头的内容和Varnish准备发送的响应中的头来决定是否发送304客户端响应状态,而不考虑后端获取是否是PASS。因此,Varnish可能会在传递后发送304客户端响应,即使后端在看到相同的请求头后选择不发送(如果响应头允许的话)。

为了保持一致性,我们进行了此更改--对于命中、未命中、命中未命中、命中换传球,以及现在的传球,是否发送304客户端响应的决定完全基于客户端请求头和响应头的内容。

您可以使用VCL方法恢复以前的行为--如果后端没有,则不要在PASS上发送304客户端响应--方法是删除 ETagLast-Modified 页眉位置 vcl_backend_response 中的If-*客户端请求标头 vcl_pass

VSL查询中的VXID

从Varnish 4.0开始,Varnish共享日志(VSL)变得更加强大,此后没有太大变化。更改通常在于在引入新功能时添加新的日志记录,或者当我们意识到某些缺失的信息确实有助于故障排除时。

依赖于VSL的Varnish实用程序(VUT)通常共享相同的 -q 查询选项,允许根据日志记录过滤交易。例如,您可能正在查找特定域上的数字::

varnishtop -i ReqURL -q 'ReqHeader:Host eq www.example.com'

而选项,如 -i-q 都仅限于日志记录,这也意味着您只能使用 X-Varnish 标题。根据事务的性质(客户端或后端),语法是不同的,您不能匹配会话。

例如,我们正在寻找最近发生的交易1234,我们希望从同一会话中收集所有信息。我们有两个选择:

# client side
varnishlog -d -g session -q 'RespHeader:X-Varnish[1] == 1234'

# backend side
varnishlog -d -g session -q 'BereqHeader:X-Varnish == 1234'

在引入之前,没有简单的方法可以使用任何事务的id来匹配它 vxid 作为可能的左侧 -q 查询表达式::

# client side
varnishlog -d -g session -q 'vxid == 1234'

# backend side
varnishlog -d -g session -q 'vxid == 1234'

# session
varnishlog -d -g session -q 'vxid == 1234'

另一个用例是收集非事务日志。使用RAW分组时,输出的组织方式不同,每条记录都以其事务ID开头,对于非事务日志,则以零开头:

# before 5.1
varnishlog -g raw | awk '$1 == 0'

# from now on
varnishlog -g raw -q 'vxid == 0'

这应该会为您提供一种更简洁、更一致的方式来过滤事务 varnishlog 还有其他的火鸡。

项目工具改进

我们在项目内部使用的工具上花费了相当多的时间。

这个 varnishtest 程序已在许多小方面进行了改进,尤其是现在使用 shellprocess 命令。如果您已经在使用,它可能会破坏现有的测试用例 varnishtest

该项目现在有了 KISS Web后端,它总结了 make distcheck 来自不同平台的结果:

http://varnish-cache.org/vtest/

如果希望在尚未介绍的平台上测试Varnish,则只需从源代码树中运行Tools/vest.sh脚本即可。我们希望看到更多的平台被覆盖(ARM64、PPC、MIPS),OS/X也会很好。

我们现在还发布我们的代码覆盖状态:

http://varnish-cache.org/gcov/

我们的目标是90%以上的覆盖率,但我们需要开始在 varnishtest 在我们可以全面测试基于诅咒(1)的程序(top/stat/hist)之前,它们目前将我们拖下水。

VMOD和Varnish API客户端应用程序作者的新闻

  • VRT版本已经升级到6.0,因为ABI有了一些变化和增加。看见 vrt.h 以获得概述。

  • 特别是,对 WS_* 用于访问工作区的界面。我们正致力于用 WS_* 函数系列,这样就不需要访问 struct ws ,它可能会在未来的版本中进行修订。目前还没有修订,所以如果您使用的是 struct ws 现在,但谨慎的做法是将该代码替换为 WS_* 在下一版本发布前的某个时间调用。如果您需要做一些工作空间界面无法处理的事情,请告诉我们。

  • libvarnishapi.so 现在从Varnish内部库导出更多元件:

    • 所有的 VTIM_* 功能--获取时钟时间、格式化和解析日期和时间格式、休眠等等。

    • 所有的 VSB_* 用于使用安全字符串缓冲区的函数。

  • varnish.m4varnishapi.pc 现在公开有关Varnish安装的更多信息。有关添加的内容的全面列表,请参阅“自5.1.0以来的评论”。

  • VMOD版本共存改进:与可执行文件不同,在Unix下,共享库不受覆盖保护,当VMOD被包管理工具更新时,这通常会造成痛苦。

    我们已经决定咬紧牙关,现在Varnishd管理进程将VMOD共享库的副本复制到workdir中的一个版本唯一的名称,运行中的VCL将从该名称访问它。这确保了无论原始VMOD文件发生什么情况,Varnishd始终可以重新启动工作进程。

    这还意味着维持跨VCL重新加载的状态的VMOD可能会中断。尽管有VMOD缓存,但仍然可以在VMOD中维护全局状态:一种解决方案是将全局状态移到单独的共享库中,该库不会被Varnish缓存。

EOF