Varnish Pass规则是否跳过request coalescing引发503问题咨询
问题根因确认
你的猜测完全属实:return(pass)会直接将请求标记为绕过缓存逻辑,直接透传至后端,完全跳过Varnish的缓存查找流程。而request coalescing(请求合并)是仅作用于进入缓存查找流程请求的特性,所有匹配你当前规则的请求都会独立向后端发起连接,高并发场景下会快速打满Varnish的后端连接配额,导致请求排队,出现busy sleep/wakeup指标上涨、503错误。此时后端本身还没到负载阈值,所以看起来运行正常。
优化方案
你可以根据实际业务需求选择以下两种方案:
方案1:保留「无指定cookie的请求完全不碰缓存」逻辑,调整透传配置避免连接打满
- 首先调整后端定义的连接池参数,适配单台Apache的实际处理能力:
backend apache1 { .host = "你的Apache内网IP"; .port = "80"; .max_connections = 200; # 按照单台Apache的最大可处理并发数调整 }
- 调整Varnish启动参数,增加
-p max_connections=65535调高全局最大连接数,增加-p timeout_idle=30缩短空闲连接回收时间,避免连接被无效占用 - 补充vcl_pass段的超时配置,避免请求长时间排队堆积:
sub vcl_pass { set req.backend_hint = 你的后端集群名; set req.timeout = 15s; # 根据业务可接受的最大延迟调整 }
方案2:调整缓存策略,仅限制响应缓存,保留请求合并能力
如果你的需求只是「不缓存无指定cookie的请求的响应」,不需要完全绕过缓存流程,可以修改配置不走return(pass),而是在后端响应段针对这类请求设置不缓存,这样请求仍会走lookup流程触发request coalescing,同一份请求在合并窗口内只会向后端发一次,大幅降低后端压力:
- 首先删除原vcl_recv中的
return(pass)逻辑,替换为给请求打标记:
sub vcl_recv { # 保留原有其他逻辑 if (!req.http.Cookie ~ "cookiename") { set req.http.X-No-Cache = "1"; } }
- 然后在vcl_backend_response段根据标记设置不缓存:
sub vcl_backend_response { if (bereq.http.X-No-Cache == "1") { set beresp.ttl = 0s; set beresp.http.Cache-Control = "no-cache, no-store, must-revalidate"; set beresp.uncacheable = true; return (deliver); } # 保留原有其他缓存逻辑 }
效果验证方式
调整配置后可以通过varnishstat命令观察核心指标:
- 关注
MAIN_backend_conn(后端连接数)、MAIN_backend_busy(忙后端连接数)的峰值是否下降 - 关注
MAIN_sleep(排队休眠次数)指标是否回归正常 - 观察
MAIN_n_reqcoalesce(请求合并次数)是否有稳定数值,说明合并机制已生效
内容的提问来源于stack exchange,提问作者Pablo R
相关产品推荐
相关产品推荐

