如何配置Varnish 3,使其根据Vary响应头条件忽略Cookie?
当然有办法!完全不需要硬编码URI,核心思路是让Varnish根据后端ESI端点返回的Vary头动态调整缓存策略——既尊重需要区分Cookie的响应,又让无需区分的响应能被所有带Cookie的请求复用。
1. 调整缓存键生成逻辑,针对ESI子请求排除默认的Cookie
Varnish 3默认会把请求的Cookie头加入缓存键,这会导致即使后端返回Vary: Accept-Encoding,不同Cookie的请求也会生成不同的缓存键。我们需要修改vcl_hash,只给主请求(非ESI)加入Cookie,ESI子请求的缓存键不包含Cookie,交给Vary头来控制变体:
sub vcl_hash { # 基础缓存键:URL + 主机(或服务器IP) hash_data(req.url); if (req.http.host) { hash_data(req.http.host); } else { hash_data(server.ip); } # 仅主请求(非ESI)才将Cookie纳入缓存键 if (req.esi_level == 0) { if (req.http.Cookie) { hash_data(req.http.Cookie); } } }
2. 让Varnish尊重后端返回的Vary头处理变体
接下来,在vcl_fetch中确保ESI响应的Vary头被Varnish正确识别,不要修改后端返回的Vary值——这样Varnish会自动根据Vary头的内容生成缓存变体:
sub vcl_fetch { # 处理ESI子请求的缓存规则 if (req.esi_level > 0) { # 确保响应可缓存(如果后端没设置Cache-Control,可添加默认规则) if (!beresp.http.Cache-Control) { set beresp.http.Cache-Control = "public, max-age=3600"; } # 关键:保留后端返回的Vary头,不做修改 # 如果后端返回Vary: Cookie, Accept-Encoding,Varnish会自动按这两个头区分变体 # 如果返回Vary: Accept-Encoding,Varnish只会按编码区分,忽略Cookie差异 } }
为什么这能解决问题?
- 对于返回
Vary: Cookie, Accept-Encoding的ESI端点:Varnish会根据Cookie和Accept-Encoding生成不同的缓存变体,确保身份验证相关的响应正确区分用户。 - 对于返回
Vary: Accept-Encoding的ESI端点:Varnish只会根据编码生成变体,完全忽略请求中的Cookie差异,所以所有带Cookie的请求都会命中同一个缓存响应,无需回源。
额外注意事项
- 确保后端返回的
Vary头准确无误:这是整个策略的核心,后端必须正确返回对应场景的Vary值。 - 如果你的主请求也需要区分Cookie,上面的
vcl_hash已经处理了,主请求的缓存键会包含Cookie,不影响主请求的缓存逻辑。
内容的提问来源于stack exchange,提问作者MicE
相关产品推荐
相关产品推荐

