首页 > 解决方案 > Varnish 缓存由 vcl_backend_error 生成的响应

问题描述

我们正在运行一个设置,其中 Varnish 将后端请求缓存到多个后端实例。这是使用 Director VMOD 处理的。当在后端服务器上完成新代码的新部署时,它们将离线几秒钟,也许一分钟,但这是一个交错部署,因此首先将代码部署到一个实例,然后再重新上线,到下一个,等等。

当一个实例正在部署时,它将关闭其网络服务器,以确保在部署过程中没有处理任何请求。为了处理这个问题,Varnish VCL 内置了一个重启循环:

sub vcl_deliver {
# Restart specifically to catch timeouts on deploy
if (resp.status >= 500) {
    # Restart goes to vcl_req and the director should choose another backend from the pool
    return(restart);
}

强制重启将导致 Director VMOD 抓取下一个未部署的实例(因为同时只有一个部署)并获得有效答案。这工作正常。

但是,当后端获取导致FetchError HTC status -1(输入的意外结束,由 web 服务器关闭 midrequest 引起)时,调用 vcl_backend_error 子例程。发生这种情况时,将按预期触发重启,但 Varnish 不会转到 vcl_backend_fetch 而是将生成的响应缓存在 VCL_backend_error 中并返回。下面是原始响应和重新启动响应的相关部分:

    VCL_call       RECV
-   VCL_return     hash
-   ReqUnset       Accept-Encoding: gzip, deflate
-   ReqHeader      Accept-Encoding: gzip
-   VCL_call       HASH
-   VCL_return     lookup
-   VCL_call       MISS
-   VCL_return     fetch
-   Link           bereq 101974384 fetch
-   Timestamp      Fetch: 1545038546.336891 8.103600 8.103600
-   RespProtocol   HTTP/1.1
-   RespStatus     503
-   RespReason     Backend fetch failed
-   RespHeader     Date: Mon, 17 Dec 2018 09:22:26 GMT
-   RespHeader     Server: Varnish
-   RespHeader     Content-Type: text/html; charset=utf-8
-   RespHeader     Retry-After: 5
-   RespHeader     X-Varnish: 101974383
-   RespHeader     Age: 0
-   RespHeader     Via: 1.1 varnish (Varnish/5.0)
-   VCL_call       DELIVER
-   VCL_return     restart
-   Timestamp      Process: 1545038546.336900 8.103608 0.000008
-   Timestamp      Restart: 1545038546.336902 8.103611 0.000003
-   Link           req 101974385 restart
-   End

    VCL_call       RECV
-   VCL_return     hash
-   VCL_call       HASH
-   VCL_return     lookup
-   Hit            101974384
-   VCL_call       HIT
-   VCL_return     deliver
-   RespProtocol   HTTP/1.1
-   RespStatus     503
-   RespReason     Backend fetch failed
-   RespHeader     Date: Mon, 17 Dec 2018 09:22:26 GMT
-   RespHeader     Server: Varnish
-   RespHeader     Content-Type: text/html; charset=utf-8
-   RespHeader     Retry-After: 5
-   RespHeader     X-Varnish: 101974385 101974384
-   RespHeader     Age: 0
-   RespHeader     Via: 1.1 varnish (Varnish/5.0)
-   VCL_call       DELIVER
-   VCL_return     restart
-   Timestamp      Process: 1545038546.336929 8.103637 0.000027
-   Timestamp      Restart: 1545038546.336932 8.103640 0.000003
-   Link           req 101974386 restart
-   End

然后它继续重新启动,从缓存中获取 503 错误,重新启动等,直到达到重新启动限制。

这种行为是故意的吗?有谁知道为什么会发生这种情况以及如何防止它?

标签: varnish

解决方案


是的,这是预期的行为。从文档:

vcl_synth 定义的对象永远不会存储在缓存中,这与 vcl_backend_error 定义的对象相反,后者可能最终会存储在缓存中。vcl_synth 和 vcl_backend_error 替换了 Varnish 3 中的 vcl_error。

像往常一样,您可以避免set beresp.uncacheable = true;vcl_backend_error.


推荐阅读