Symfony Sulu集成Varnish ESI失效问题排查求助
排查ESI失效问题的具体步骤
1. 确认主页面的缓存生命周期
- 用
curl -I http://your-domain/your-page检查主页面的Cache-Control头:如果主页面设置了很长的max-age(比如1天)且没有must-revalidate,Varnish会一直返回缓存的主页面,根本不会去后端拉取带最新ESI标签的版本。 - 用
varnishlog -g request -q "ReqUrl ~ '/your-page'"查看主页面的缓存命中情况:如果一直显示Hit,说明主页面缓存没过期,Varnish不会触发新的后端请求,自然不会解析新的ESI。 - 确认主页面响应头包含
Surrogate-Control: content="ESI/1.0":这个是Varnish开启ESI解析的核心触发条件,必须由Symfony后端返回,不能只在VCL里配置。
2. 检查ESI片段的缓存与个性化配置
- 直接请求ESI片段URL(比如
curl http://localhost:8000/esi/login-button),确认10秒后内容是否更新:如果直接请求后端都不更新,问题出在Symfony控制器,和Varnish无关。 - 检查片段的响应头:必须包含
Cache-Control: public, max-age=10, shared-max-age=10,关键是要加Vary: Cookie——登录按钮是用户个性化内容,没有Vary: Cookie的话,Varnish会把登录/未登录状态的片段缓存成同一个版本,即使过期刷新也不会变。 - 用
varnishlog -g request -q "ReqUrl ~ '/esi/login-button'"查看片段的缓存命中:10秒后应该出现Miss,如果一直Hit,说明片段的缓存策略被覆盖(比如Symfony的其他缓存层、VCL里强制设置了更长的缓存时间)。
3. 验证VCL的ESI配置正确性
- 确保
vcl_recv里给后端发送了ESI支持声明:sub vcl_recv { # 告诉Symfony可以返回ESI标签 set req.http.Surrogate-Capability = "ESI/1.0"; } - 确保
vcl_backend_response里正确开启ESI解析,且逻辑顺序正确(要在设置beresp.cacheable之前):sub vcl_backend_response { # 检测到后端返回的Surrogate-Control头,开启ESI解析 if (beresp.http.Surrogate-Control ~ "ESI/1.0") { unset beresp.http.Surrogate-Control; set beresp.do_esi = true; } # 其他缓存配置放在后面 if (beresp.cacheable) { # 你的xkey等缓存失效配置 } } - 确认Varnish版本支持ESI:Varnish 6.x及以上版本默认支持,老版本可能需要额外编译模块。
4. 排查Docker链路与额外缓存层
- 确认Varnish的后端指向NGINX(8000端口),而不是直接指向PHP(9000端口):Varnish无法直接处理FastCGI请求,必须通过NGINX转发。
- 检查NGINX是否开启了自身的缓存:如果NGINX配置了
proxy_cache,会直接返回缓存的页面/片段,绕过Varnish的ESI解析。 - 检查Sulu的CMS缓存:Sulu自带页面缓存机制,可能覆盖了Symfony的ESI设置,需要在Sulu的页面配置里禁用静态缓存,或者配置支持ESI。
内容的提问来源于stack exchange,提问作者hsmsm
相关产品推荐
相关产品推荐

