事情本身不复杂,线索都在日志里。CDN 后台显示缓存命中率只有 5%,源站压力一直下不来,抓包发现每个请求的 Cookie 都不同,边缘节点把它们当成了不同的资源。

第一反应是「静态资源也带着会话 Cookie,命中率被拖低」,验证下来不成立。

排查方向其实有限,先把可能性排一排。缓存键默认包含完整 Cookie,会话不同就各存一份。另一种情况是源站返回了 Vary: Cookie,进一步放大了缓存碎片。

还有一种情况,查询参数没有做归一化,顺序不同算成两个键。

动手时先看响应头里的 Vary 和缓存键配置

curl -sI https://www.example.com/a/1.html | grep -i -E 'vary|cache-control'

然后对比两次请求的缓存状态

curl -sI -H 'Cookie: sid=1' https://www.example.com/a/1.html | grep -i x-cache; curl -sI -H 'Cookie: sid=2' https://www.example.com/a/1.html | grep -i x-cache

随后把静态资源的 Cookie 去掉

proxy_ignore_headers Set-Cookie;
proxy_hide_header Set-Cookie;

缓存键只保留路径与必要参数

proxy_cache_key "$scheme$host$uri";

恢复的判定其实很直接。静态资源的命中率升到 90% 以上,回源带宽下降六成,蜘蛛抓取时的响应时间同步缩短。

缓存键把 Cookie 算进去,等于给每个访客单独存一份,命中率低是必然结果。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。

作者 9823189