Varnish自定义哈希函数下SSR与AJAX请求未命中共享缓存问题
问题根因排查结论
问题的核心原因是响应头Vary的多变体匹配规则导致的缓存未命中,和你自定义的哈希逻辑没有关系。
具体原理
Varnish的缓存匹配分为两个独立步骤:
- 第一步通过
vcl_hash计算的哈希值,定位到对应的缓存对象组 - 第二步检查该组内缓存对象的
Vary响应头声明的所有请求头,是否和当前请求的对应头完全匹配,只有全部匹配才会命中缓存
如果匹配失败,就算哈希值完全一致,Varnish也会判定为MISS,回源获取新的响应,作为该哈希下的另一个变体存储,不会复用之前的缓存。
匹配你的场景的核心证据
你的日志完全符合该特征:
- 请求1、2都是SSR发起的同类型请求,所有被
Vary声明的请求头完全一致,因此请求2命中缓存 - 请求4是浏览器发起的AJAX请求,
Accept/Accept-Encoding/User-Agent等被Vary声明的请求头和SSR请求的对应头不一致,导致Vary匹配失败,出现非预期MISS - 请求6和请求4都是浏览器发起的同类型请求,请求头完全一致,因此命中请求4回源生成的新缓存变体
修复方案
你可以根据需求选择以下任意一种方案:
- 后端服务移除不必要的Vary声明:如果返回的内容和
Accept/Accept-Encoding/User-Agent等头无关,直接在后端删除这些Vary配置即可 - 在VCL的
vcl_backend_response阶段清理不必要的Vary头:示例代码如下:
sub vcl_backend_response { # 仅保留业务需要的Vary头,比如仅保留Locale set beresp.http.Vary = "Locale"; # 额外清理可能导致匹配失败的Set-Cookie头,避免默认不缓存 unset beresp.http.Set-Cookie; }
- 在
vcl_recv阶段清理无关请求头:如果是给未登录用户提供缓存,可以直接清理Cookie等无关头,避免Vary: Cookie导致的匹配失败:
sub vcl_recv { # 清理未登录用户的Cookie,避免影响缓存匹配 unset req.http.Cookie; }
内容的提问来源于stack exchange,提问作者wawa
相关产品推荐
相关产品推荐

