死链扫描工具:异常恢复后怎样区分缓存过期与真正修复

📍 WDQWDWQD987AAAAA:216.73.216.82
📱 Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)
🔗 /e00e3b5a9cde.html
📄

死链扫描工具:异常恢复后怎样区分缓存过期与真正修复

先看一个可操作的判断:把同一批 URL 分成两组,一组带上能绕开缓存的查询参数重新请求,另一组保持原样请求,然后比较两组返回的状态码、响应头和响应体是否一致。如果只有原样请求返回 200,而带参数请求仍然返回 404 或 410,那更可能是缓存过期或中间层缓存被刷新,而不是源站真正修复;如果两组都返回同样的正常结果,才谈得上源站层面可能已经修复。

为什么异常恢复后的第一个 200 不能直接当成修复

死链扫描工具在异常恢复后重新跑一遍,看到原本报 404 的 URL 变成 200,很容易被理解成“已经修好了”。但这个 200 可能来自多个位置:源站确实补上了内容;CDN 或反向代理缓存了一份旧的正常响应;站点在维护窗口结束后重新上线;甚至扫描工具本身的重试逻辑拿到了不同的节点结果。

缓存过期和真正修复的区别在于,前者是“某一份副本变正常了”,后者是“源站对这类请求稳定地给出正常响应”。判断时不要只看一次扫描结果,而要看同一 URL 在不同请求条件下是否表现一致。

用三组证据把两种解释分开

下面这组检查不依赖具体工具品牌,任何能自定义请求头和查询参数的扫描方式都可以做。假设某条 URL 在异常恢复后从 404 变成 200,按顺序验证:

  1. 绕缓存请求:在 URL 后附加一个每次不同的查询参数,例如 ?probe=时间戳,让缓存键发生变化。如果这条请求仍返回 404,说明源站并没有真正提供内容,之前的 200 来自缓存层。
  2. 响应头核对:对比两次响应的 Age、Cache-Control、X-Cache 一类字段。若 200 响应的 Age 明显偏大,或带有命中缓存的标记,而绕缓存请求没有这些特征,缓存过期的解释更成立。注意不同 CDN 的头字段命名不同,需要按实际响应判断,不能套用固定字段名。
  3. 响应体比对:把 200 响应的正文与站点正常页面的结构对比。如果正文是缓存的旧版本、占位页或错误页被包装成 200,那属于“状态码正常但内容不对”,同样不算修复。

如果三组证据都指向源站稳定返回正确内容,才可以把这批 URL 从待修复清单移出。否则应保留在清单里,并标注“疑似缓存”。

一个会让上述结论失效的反例

上述方法有一个明确的失效条件:当站点对带查询参数的 URL 做了统一跳转或统一拦截时,绕缓存请求本身就不再代表源站的真实响应。例如某些站点把所有带未知参数的请求 301 到首页,或者直接返回 403,那么“带参数请求返回 404”就不能证明源站没修复,只能说明这条探测路径被站点规则改写了。

遇到这种情况,需要换一种绕缓存方式,比如改用不同的请求头、不同的 HTTP 方法,或直接从源站 IP 发起请求并带上正确的 Host。若这些条件都不具备,就不要用单次探测下结论,而应把判断降级为“证据不足”。

把判断结果写回扫描流程

区分清楚之后,下一步动作应该落到扫描配置上,而不是停留在人工记忆里。具体做法是:在死链扫描工具的规则中,把“绕缓存请求仍失败”的 URL 标记为待修复,把“仅原样请求恢复”的 URL 标记为待观察,并记录首次观察到恢复的时间点。

这个动作会直接影响后续判断:待观察的 URL 在下一轮扫描中如果再次变回 404,说明此前的 200 只是缓存窗口内的假象,应重新进入修复流程;如果连续多轮绕缓存请求都正常,才升级为已修复。这样做的代价是需要多跑几轮扫描,但能避免把缓存刷新误报成修复完成,减少与开发人员的无效交接。

另外要记住,robots.txt 的抓取限制不等于可靠的索引移除,站点地图也不保证收录,这些与死链状态判断是不同层面的问题,不能互相替代。

什么时候可以直接判定为真正修复

当满足以下条件时,可以较有把握地认为源站已经修复:绕缓存请求稳定返回正确状态码和正确内容;响应头中没有明显的缓存命中特征;连续两次以上、间隔足够长的扫描结果一致;并且该 URL 在站点内部链接或站点地图中的引用关系也已同步更新。

如果只满足其中一部分,就保留“缓存过期”作为备选解释,继续观察。判断死链是否真正修复,本质上是在比较不同请求路径下的一致性,而不是看某一个瞬间的状态码。

图1 图2

nginx