结论先说:只有当你能让同一次请求在每一层缓存上留下可对比的响应标识时,才适合用逐层剥离的方式定位;如果各层缓存对同一资源的变体键(Vary、设备、语言、Cookie)定义不一致,逐层剥离只会把问题越拆越乱,此时应先统一变体策略再排查。蜘蛛爬行优化在这里的核心不是让蜘蛛多来,而是确保它拿到的每个版本都是你愿意让它看到的版本。
多层缓存常见于 CDN 边缘节点、反向代理(如 Nginx、Varnish)与应用内缓存三层叠加。返回不同版本通常不是某一层坏了,而是三层对“同一个 URL 是否算同一份资源”的判断不同。你需要逐层确认三件事:
Accept-Encoding 分桶,中间层却按 User-Agent 分桶,两者就会各自命中不同副本。可执行动作:给每一层响应加一个自定义头,例如 X-Cache-Layer: edge、X-Cache-Layer: proxy、X-Cache-Layer: app,并用同一个 URL、同一组请求头反复请求。如果三层标识对应的内容哈希不同,就说明变体键没对齐,此时继续往下拆没有意义。
返回不同版本有两种完全不同的原因,处理方向相反:
Cache-Control: no-cache)始终返回同一内容。区分方法:固定 URL 和请求头,连续请求若干次并记录每层标识与内容哈希。若只有边缘层结果跳变、回源结果稳定,问题在缓存;若回源结果本身就随参数变化,问题在源站逻辑,缓存只是如实放大了它。这一步的结论直接决定下一步找谁:前者找缓存配置,后者找应用路由或灰度规则。
假设某页面边缘缓存 TTL 为 10 分钟,反向代理 TTL 为 1 小时,应用缓存 TTL 为 24 小时。你在发布新模板后立即用蜘蛛常用的请求头抓取,可能拿到应用层 24 小时前的旧版本,而普通浏览器请求命中刚回源的边缘新版本。此时你会误判为“蜘蛛被区别对待”,实际只是各层刷新节奏不同。
验证方式:在发布后按固定间隔(例如每 5 分钟)记录三层标识与内容哈希,观察旧版本在哪一层最后消失。如果旧版本在应用层停留最久,说明需要主动失效应用缓存,而不是改 robots.txt 或站点地图。注意,robots.txt 的抓取限制并不等于可靠的索引移除,改它解决不了缓存版本问题。
反例:当各层缓存对 Vary 的处理本身就不一致时,逐层剥离得到的“稳定版本”可能只是某一层的偶然命中。比如边缘层不支持某个 Vary 维度而中间层支持,你看到的稳定结果并不代表源站稳定。此时正确顺序是先统一变体键定义,再谈定位。若业务依赖按地域或登录态返回不同内容,还必须先明确哪些维度允许进入缓存键,否则任何剥离结论都不可靠。
确认是缓存不一致后,优先做两件事:统一各层 TTL 与变体键,并为关键页面提供主动失效通道(如按 URL 或标签清除)。确认是源站多版本后,检查这些版本是否都符合你的蜘蛛爬行优化预期——如果不希望某个版本被抓取,应在源站层面控制返回,而不是依赖缓存偶然命中。HTTPS 不保证内容版本一致,也不解决缓存分层问题。最后,用同一组请求头在修复前后各记录一轮三层标识与内容哈希,只有三层一致且可复现,才能认为问题已收敛。