先给结论:当同一个 URL 在 CDN、反向代理、应用缓存和搜索引擎快照里出现不同版本时,不要先改缓存时间,而要先固定一个可复现的请求条件,逐层比对响应。因为多层缓存不一致通常是“某一层按自己的规则缓存了另一个变体”,盲目清缓存只会让问题在几小时后复发。
假设你更新了页面标题,源站已经返回新版本,但带查询参数的 URL 仍是旧版本,搜索引擎抓到的又是第三版。此时如果直接刷新整站缓存,可能把原本正确的变体也一起清掉,各层重新回源的时间不同,短时间内会出现更多版本组合。要定位的是“哪一层在什么条件下缓存了哪个变体”,而不是缓存本身。
解释一:各层把不同请求当成不同资源。 CDN 可能按完整 URL 缓存,反向代理按 Host 加路径缓存,应用层再按语言、设备或登录状态分桶。只要某一层的缓存键忽略了某个维度,它就会把 A 变体的响应交给 B 变体的请求。此时现象是:同一路径在带与不带某个参数、或不同 Accept-Language 下返回不同内容。
解释二:回源请求被中间层改写或拦截。 某一层回源时被重定向、被要求带特定请求头,或遇到 robots.txt 限制抓取路径,于是它缓存了错误页、旧页或空响应。此时现象是:源站直接访问正常,但经过某一层后内容不同,且差异集中在特定路径或特定状态码上。
用同一组请求条件逐层抓取,记录状态码、响应头和正文关键片段,而不是只看页面外观。可区分点如下:
这里要注意:请求量或抓取量下降、某个快照消失,都不能单独证明你处理对了。它们也可能来自抓取配额调整、站点结构变化或正常刷新周期。判断依据应是同一请求条件下各层响应是否收敛到同一版本。
先选一个受影响 URL,固定请求方法、路径、查询参数和关键请求头,分别向源站、反向代理、CDN 边缘节点发起请求,记录每一层的状态码、Cache-Control、Age、ETag 或 Last-Modified,以及正文中一个唯一标识(例如标题或版本号)。把结果按“层—条件—版本”列成对照。若某一层在多个条件下都返回同一旧版本,下一步就检查该层的缓存键和回源规则;若只有带特定参数的请求出错,下一步就统一各层的变体归一化规则,而不是继续清缓存。
假设某页面在 CDN 上带 ?from=nav 返回旧标题,不带参数返回新标题,源站两者都返回新标题。按照前面的对照方法,可以判断问题出在 CDN 把查询参数纳入了缓存键,而反向代理没有。此时先统一缓存键规则,再让 CDN 按新规则回源,比直接清空整个 CDN 缓存更可控。反过来,如果源站在带参数时也返回旧标题,那问题在应用层或上游数据,不在 CDN。
需要说明的是,robots.txt 的抓取限制不等于可靠的索引移除,站点地图也不保证收录,这些手段不能替代对缓存一致性的排查。定位完成后,用同一组固定条件复测各层响应,确认它们收敛到同一版本,再决定是否需要提交更新或等待自然刷新。