Varnish后端宕机时无法继续提供缓存服务的配置问题咨询
配置核心问题与修复方案
已存在的问题
- 重复定义了
vcl_recv子例程,VCL中重复定义同个子例程时,后定义的会完全覆盖前一个,你用于分配后端路由的第一个vcl_recv逻辑完全没有生效,流量路由规则错误是触发503的核心原因之一。 - 未在
vcl_recv中显式声明允许使用的 grace 时长,Varnish无法自动启用你在后端响应中设置的12小时 grace 模式。 - 硬刷新的 ban 逻辑未做后端健康判断,无论后端是否可用,只要收到
Cache-Control: no-cache头就会清除对应缓存,后端宕机时会直接清空可用的缓存内容。 - Ban 规则的匹配字段和存储的缓存标记不匹配,你在
vcl_backend_response中存了x-host和x-url作为缓存标记,但Ban规则用的是原始req.host和req.url,可能出现无法命中Ban规则的问题。 - 缺少后端错误时的兜底返回逻辑,后端返回5xx时没有优先返回陈旧缓存的规则。
具体修改步骤
- 合并两个
vcl_recv子例程,把后端路由逻辑放到第二个vcl_recv的最开头:
sub vcl_recv { # 原第一个vcl_recv的后端分配逻辑移到这里 if (req.http.host == "example.com" || req.http.host == "example2.com") { set req.backend_hint = server_b.backend(); } elseif (req.http.host == "example3.com") { set req.backend_hint = server_c.backend(); } else { set req.backend_hint = server_a.backend(); } # 原第二个vcl_recv的所有逻辑接在后面 set req.http.X-Forwarded-For = regsub(req.http.X-Forwarded-For,"^([^,]+)(,[^,]+)*","\1"); # ...... 剩余原有逻辑不变 }
- 在
vcl_recv中添加 grace 启用配置,可以加在后端分配逻辑之后:
# 允许最多使用12小时的陈旧缓存,和beresp.grace配置对齐 set req.grace = 12h;
- 修改硬刷新的Ban规则,添加后端健康判断,把原有逻辑替换为:
# 只有后端健康时才执行硬刷新清缓存逻辑,后端宕机时跳过 if (std.healthy(req.backend_hint) && req.http.Cache-Control == "no-cache") { ban("obj.http.x-host == " + req.http.host + " && obj.http.x-url == " + req.url); }
- 添加后端错误兜底逻辑,新增
vcl_backend_error子例程:
sub vcl_backend_error { # 后端返回错误时优先返回已有的陈旧缓存 if (stale.exists) { return (deliver_stale); } return (deliver); }
- 可选优化:如果需要后端宕机时更长时间返回缓存,可以把
beresp.grace从12h调整为更长的时长,比如7d。如果同站点有多台后端,建议用directors把后端组成资源池,健康检查会对整个池生效,避免单后端挂了就判定整体异常。
内容的提问来源于stack exchange,提问作者user14709644
相关产品推荐
相关产品推荐

