先给有条件的结论:当同一死链在不同层返回的版本不一致时,优先怀疑“缓存层各自持有了不同时间点的响应”,而不是死链本身被修好了。要定位一致性,必须把每一层的响应当独立证据采样,而不是只看浏览器或单一节点。只有当各层对同一请求的响应头、状态码和缓存键都能对齐后,才能判断死链处理是否真正生效。
多层缓存下,不一致通常表现为状态码、响应头或正文三者之一不同。不要用“页面看起来变了”作为判断依据,因为浏览器可能命中本地缓存,而中间层仍返回旧副本。一个可核对的证据是:同一 URL 在固定请求头下,分别记录状态码、Age、Cache-Control、ETag 或 Last-Modified,以及正文首段。若状态码在 404 与 200 之间摆动,说明至少有一层缓存了旧的成功响应,而源站已改为死链处理。
实际操作上,可以先用固定请求头逐层请求,而不是依赖浏览器。动作是:对同一 URL 分别从客户端、CDN 边缘、反向代理和源站各取一次响应,记录上述字段。结果会直接影响下一步——如果只有边缘层返回 200,而源站返回 404,那么问题不在死链规则,而在边缘缓存未失效;如果源站也返回 200,则要检查死链处理逻辑是否真的命中该 URL 规则。
不同层可能因为缓存键不同而返回不同版本。例如 CDN 按完整 URL 加查询字符串缓存,反向代理却忽略查询字符串,于是带参数的请求命中一个旧副本,不带参数的命中新副本。另一种情况是请求头差异:某些层对 Accept-Encoding 或 User-Agent 做变体缓存,导致同一 URL 出现多个版本。要验证这一点,可以固定请求头后再逐层请求,观察响应是否收敛。若收敛,说明不一致来自缓存键或变体,而不是死链处理本身。
假设一个场景:某 URL 已加入死链处理,源站返回 404,但 CDN 边缘仍返回 200 且 Age 很大。此时先不要急着刷新全站缓存,而应取该边缘节点的响应头,确认它是否携带了旧的 Cache-Control。如果旧响应头允许长缓存,那么边缘层只是按旧规则持有副本。下一步动作是让源站返回明确的失效信号,并确认边缘层是否按该信号更新。这个动作的结果会影响后续判断:若边缘层更新后仍返回 200,则要怀疑有中间层未传递失效信号。
分层采样是区分两种解释的关键。第一种解释是死链处理已生效,但缓存层未同步;第二种解释是死链处理规则未覆盖该 URL,缓存层只是如实返回了源站的 200。区分方法是对同一 URL 同时记录源站响应和缓存层响应。若源站为 404、缓存层为 200,则属于缓存未同步;若源站也为 200,则属于规则未生效。不要用“抓取量归零”或“某层请求量下降”单独证明处理正确,因为这些现象也可能来自抓取预算调整、robots.txt 限制或外部链接变化。
这里有一个反例会使上述结论失效:如果源站本身在多台后端之间返回不同版本,那么缓存层只是放大了不一致,而不是造成不一致。此时逐层请求会看到源站内部也不一致,需要先统一源站响应,再谈缓存同步。换句话说,多层缓存不一致只是症状,源站多副本不一致才是病因。若忽略这一点,只清缓存,问题会再次出现。
在证据未固定前,不要批量刷新所有缓存。建议按以下顺序推进:
Age、Cache-Control 和正文首段。这个顺序的结果会决定下一步:如果失效后各层收敛到同一状态码,说明问题在缓存同步;如果失效后仍不收敛,则要回到源站和缓存键规则,检查是否存在未被发现的变体或中间层。死链处理的一致性,最终不取决于清了多少次缓存,而取决于每一层是否对同一请求给出可核对的相同响应。