清漆超时 命中未命中注意缓存 Set-Cookie 标头我没有看到任何缓慢的响应

问题描述

希望有人能指出我正确的方向。我们继承了一个商店网站的 vcl。

基本设置是:

Nginx ssl 终止 -> varnish -> varnish rr 到 4 个 apache 后端

设置工作正常,但是当我们将其置于任何形式的负载下(大约 250 个并发)时,Nginx 开始报告它无法连接到 varnish:

2021/07/23 12:08:15 [error] 25348#25348: *7223 upstream timed out (110: Connection timed out) while reading upstream,client: xx,server: _,request: "GET / HTTP /1.1”,上游:“http://xx/”,主机:“xx”

并且清漆报告它已经损坏了管道:

*   << Request  >> 5996617   
-   Begin          req 5996616 rxreq
-   Timestamp      Start: 1627038436.200604 0.000000 0.000000
-   Timestamp      Req: 1627038436.200604 0.000000 0.000000
-   ReqStart       xx 42403
-   ReqMethod      GET
-   ReqURL         /
-   ReqProtocol    HTTP/1.1
-   ReqHeader      X-Real-IP: xx
-   ReqHeader      X-Forwarded-For: xx
-   ReqHeader      X-Forwarded-Proto: https
-   ReqHeader      X-Forwarded-Port: 443
-   ReqHeader      Host: xx
-   ReqHeader      Connection: close
-   ReqHeader      Accept: */*
-   ReqHeader      Accept-Language: en
-   ReqHeader      User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0; .NET CLR 1.1.4322; .NET CLR 1.0.3705; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)
-   ReqHeader      Accept-Encoding: gzip,deflate
-   ReqHeader      Dotcom-ProxyIDTag: 13
-   ReqUnset       X-Forwarded-For: xx
-   ReqHeader      X-Forwarded-For: xx,xx
-   VCL_call       RECV
-   ReqURL         /
-   ReqURL         /
-   ReqURL         /
-   ReqURL         /
-   ReqURL         /
-   ReqURL         /
-   ReqURL         /
-   ReqURL         /
-   ReqURL         /
-   ReqURL         /
-   ReqURL         /
-   ReqURL         /
-   ReqURL         /
-   ReqHeader      Surrogate-Capability: shopware=ESI/1.0
-   ReqUnset       X-Forwarded-Proto: https
-   ReqHeader      X-Forwarded-Proto: https
-   ReqHeader      X-UA-Device: desktop
-   ReqHeader      X-UA-vendor: generic
-   ReqHeader      X-UA-Forced: no
-   ReqUnset       Accept-Encoding: gzip,deflate
-   ReqHeader      Accept-Encoding: gzip
-   VCL_return     hash
-   VCL_call       HASH
-   VCL_return     lookup
-   Hit            4653975
-   VCL_call       HIT
-   VCL_acl        NO_MATCH editors
-   VCL_return     deliver
-   RespProtocol   HTTP/1.1
-   RespStatus     200
-   RespReason     OK
-   RespHeader     Date: Fri,23 Jul 2021 10:54:07 GMT
-   RespHeader     Server: Apache
-   RespHeader     Expires: Thu,19 Nov 1981 08:52:00 GMT
-   RespHeader     Pragma: no-cache
-   RespHeader     Cache-Control: max-age=14400,public,s-maxage=14400
-   RespHeader     X-Shopware-Allow-Nocache: admin-1,price-1
-   RespHeader     X-Shopware-Cache-Id: ;c3;
-   RespHeader     Set-Cookie: session=; path=/
-   RespHeader     Set-Cookie: lastAffiliate=na; path=/
-   RespHeader     Server-Id: web3
-   RespHeader     Content-Type: text/html; charset=UTF-8
-   RespHeader     X-Content-Length: 17190
-   RespHeader     content-encoding: gzip
-   RespHeader     vary: Accept-Encoding
-   RespHeader     X-Varnish: 5996617 4653975
-   RespHeader     Age: 788
-   RespHeader     Via: 1.1 varnish-v4
-   VCL_call       DELIVER
-   VCL_acl        NO_MATCH editors
-   RespUnset      X-Shopware-Allow-Nocache: admin-1,price-1
-   RespUnset      X-Shopware-Cache-Id: ;c3;
-   RespUnset      Cache-Control: max-age=14400,s-maxage=14400
-   RespHeader     Cache-Control: max-age=0,private
-   RespUnset      Set-Cookie: session=; path=/
-   RespUnset      Set-Cookie: lastAffiliate=na; path=/
-   RespHeader     X-Cache: HIT
-   RespHeader     X-Cache-Hits: 3611
-   VCL_return     deliver
-   Timestamp      Process: 1627038436.200763 0.000159 0.000159
-   RespHeader     Accept-Ranges: bytes
-   RespHeader     transfer-encoding: chunked
-   Debug          "RES_MODE 18"
-   RespHeader     Connection: close
-   Link           req 5996618 esi
-   Debug          "Write error,retval = -1,len = 14,errno = broken pipe"
-   Timestamp      Resp: 1627038513.810060 77.609456 77.609297
-   ReqAcct        522 0 522 456 5368 5824
-   End            

清漆统计显示

Uptime mgt:     1+04:38:26                                                               Hitrate n:       10       21       21
Uptime child:   1+04:38:26                                                                  avg(n):   0.4843   0.4762   0.4762

    NAME                                        CURRENT        CHANGE       AVERAGE        AVG_10       AVG_100      AVG_1000
MAIN.uptime                                  1+04:38:26
MAIN.sess_conn                                    10107          5.99           .            4.97          4.89          4.89
MAIN.client_req_400                                   9          0.00           .            0.00          0.00          0.00
MAIN.client_req                                   10815          5.99           .            4.97          4.89          4.89
MAIN.cache_hit                                    14952          8.99           .            7.83          7.69          7.69
MAIN.cache_miss                                   16483          8.99           .            7.83          7.69          7.69
MAIN.backend_conn                                   890          0.00           .            0.18          0.15          0.15
MAIN.backend_reuse                                24251          7.99           .           10.20         10.14         10.14
MAIN.backend_recycle                              25012          9.99           .           10.55         10.38         10.38
MAIN.fetch_length                                 24022          9.99           .           10.55         10.38         10.38
MAIN.fetch_chunked                                  755          0.00           .            0.00          0.00          0.00
MAIN.fetch_eof                                        2          0.00           .            0.00          0.00          0.00
MAIN.fetch_none                                      33          0.00           .            0.00          0.00          0.00
MAIN.fetch_304                                      319          0.00           .            0.00          0.00          0.00
MAIN.fetch_Failed                                    13          0.00           .            0.00          0.00          0.00
MAIN.pools                                            2          0.00           .            2.00          2.00          2.00
MAIN.threads                                        600          0.00           .          600.00        600.00        600.00
MAIN.threads_created                                738          0.00           .            0.00          0.00          0.00
MAIN.threads_destroyed                              138          0.00           .            0.00          0.00          0.00
MAIN.busy_sleep                                35286304      62859.00        342.00      34852.46      32989.42      32989.42
MAIN.busy_wakeup                                     51          0.00           .            0.00          0.00          0.00
MAIN.sess_queued                                    138          0.00           .            0.00          0.00          0.00
MAIN.n_object                                       344         -2.00           .          344.38        344.33        344.33
MAIN.n_objectcore                                   598          0.00           .          600.20        601.14        601.14
MAIN.n_objecthead                                   865          0.00           .          865.00        865.00        865.00
vvv MAIN.uptime                                                                                                  INFO  1-25/96

并非所有请求都失败,概率约为 70%。

后端几乎没有受到影响,即使我删除Nginx 并且只是在 http 上使用 varnish 接受 http 连接的网站,也会发生 varnish 错误

在 Centos7 上运行 4.1.11(也尝试过 v6,在 Centos8 和 Ubuntu 20 上也试过)。打开的文件增加了,似乎没有资源被最大化。

任何指针表示赞赏。我觉得忙碌的睡眠是我应该寻找的地方,但看不到它继续增长的任何理由。

谢谢


看起来命中正在生成一个 esi 子请求:

-   Timestamp      Start: 1627115035.167388 0.000000 0.000000
-   BereqMethod    GET
-   BereqURL       /?action=shopMenu&controller=index&module=widgets&sCategory=3
-   BereqProtocol  HTTP/1.1
-   BereqHeader    X-Real-IP: 
-   BereqHeader    X-Forwarded-Port: 443
-   BereqHeader    Accept: */*
-   BereqHeader    Accept-Language: en
-   BereqHeader    User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0; .NET CLR 1.1.4322; .NET CLR 1$
-   BereqHeader    Dotcom-ProxyIDTag: 5
-   BereqHeader    Host: 
-   BereqHeader    X-Forwarded-For: 
-   BereqHeader    Surrogate-Capability: shopware=ESI/1.0
-   BereqHeader    X-Forwarded-Proto: https
-   BereqHeader    X-UA-Device: desktop
-   BereqHeader    X-UA-vendor: generic
-   BereqHeader    X-UA-Forced: no
-   BereqHeader    Accept-Encoding: gzip
-   BereqHeader    X-Varnish: 4489358
-   VCL_call       BACKEND_FETCH
-   VCL_return     fetch
-   BackendOpen    414 boot.web4  50444
-   BackendStart   
-   Timestamp      Bereq: 1627115035.167506 0.000118 0.000118
-   Timestamp      Beresp: 1627115035.368178 0.200790 0.200672
-   BerespProtocol HTTP/1.1
-   BerespStatus   200
-   BerespReason   OK
-   BerespHeader   Date: Sat,24 Jul 2021 08:23:55 GMT

后端正在快速响应这些请求,我在 Apache 中没有看到任何失败的请求。我需要考虑在 vcl 中缓存这些请求吗?

解决方法

日志的有趣之处在于我们正在处理缓存命中。这应该意味着超时不是由缓慢的后端引起的。

但是,以下日志行可能表明 ESI 子请求导致超时:

-   Link           req 5996618 esi
-   Debug          "Write error,retval = -1,len = 14,errno = Broken pipe"
-   Timestamp      Resp: 1627038513.810060 77.609456 77.609297

ESI 子请求

此 ESI 子请求的事务 ID 为 5996618Timestamp 日志行的最后一列值显示 Varnish 77 秒生成响应,而之前的 Timstamp 条目仅在 159 微秒,如下图所示:

-   Timestamp      Process: 1627038436.200763 0.000159 0.000159

一个合理的假设是,ESI 占位符代表必须来自后端的有状态数据,并且可能需要一些时间,尤其是在负载较重的情况下。

我还假设损坏的管道不是由 Varnish 引起的,而是由 Nginx 超时引起的。这是有道理的,因为 Nginx 不会永远等待。

下一步

下一步是检查完整日志,包括 ESI 调用的日志项。

根据 ESI 调用的目的,我们可以看看如何从源头减轻一些压力并使响应时间恢复正常。

如果这个 ESI 子请求端点被命中太多,合成响应并在 Varnish 中执行一些决策是有意义的。

另一种方法是通过在 Redis 中存储投影数据,在您的应用程序中对该端点使用更快的数据访问。

如果您需要更多帮助,请更详细地描述 ESI 情况,添加完整的日志,也可能添加完整的 VCL 文件以供参考。

我在 https://pastebin.com/nMwd72B4 中看到的是响应速度非常快的 ESI 子请求。其中一些 ESI 调用会被缓存,其他则不会。

命中未命中

但我发现您的 VCL 配置存在一个大问题:

set beresp.ttl = 0s;
set beresp.uncacheable = true;
return (deliver);

不可缓存的数据永远不应该出现在等待列表中,因为 Varnish 的内置请求合并功能永远无法并行满足这些请求。所以它们最终被串行处理,这是非常非常慢的。尤其是在重载的情况下。

通常,不可缓存的响应会添加到 Hit-For-Miss 缓存中,其中缓存了不缓存的决定。听起来很讽刺,但确实有用。

Hit-For-Miss 列表中的对象将自动绕过等待列表。这是针对具有 set beresp.uncacheable = true 的响应完成的。

你的问题是 TTL 设置为零,这是一个很大的禁忌!

内置 VCL 行为将 Hit-For-Miss 对象的 TTL 设置为 2 分钟,如 https://github.com/varnishcache/varnish-cache/blob/6.0/bin/varnishd/builtin.vcl#L164 所示。

这是您需要的:

set beresp.ttl = 120s;
set beresp.uncacheable = true;
return (deliver);

我并不是说这会解决您的所有问题,但它可能有助于提高性能,因为序列化将不再有效。

我还在包含 Set-Cookie 标头的日志中看到了相当多的缓存命中。

Varnish 的内置 VCL 行为不会缓存包含 https://github.com/varnishcache/varnish-cache/blob/6.0/bin/varnishd/builtin.vcl#L158 中所见的 Set-Cookie 标头的对象,因为 Set-Cookie 标头暗示的个性化级别不适用于收到回复的每个人。

如果这是故意的,请忽略此评论。如果没有,以下是您的一些选择:

  • 尽可能去掉 Set-Cookie 标头
  • 对某些包含 Set-Cookie 标头的响应绕过缓存。
  • 覆盖 VCL 代码中 Set-Cookie 标头的值

我没有看到任何缓慢的响应

您提供的 Pastbin 链接不包含任何特别慢的 Timestamp 标签。也许这些日志项是在系统负载不大时记录的。

我很想看到完整的日志事务,包括与我在您的原始问题中看到的 - Timestamp Resp: 1627038513.810060 77.609456 77.609297 的性能相匹配的 ESI 子请求。

但是,请务必关注候补名单的部分,也许这会解决您的问题。