死链检测工具:多层缓存返回不同版本时怎样定位一致性问题

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

死链检测工具:多层缓存返回不同版本时怎样定位一致性问题

先给结论:不要用死链检测工具反复重扫来“刷出一致结果”,而要把检测请求分成两类——一类绕过缓存直连源站,用来确认源站真实状态;一类保留完整缓存链路,用来确认用户实际拿到的状态。两类结果不一致时,问题不在死链本身,而在某一层缓存的键、过期策略或回源规则。定位动作是先固定一个 URL 作为探针,逐层剥离缓存,再决定是改缓存配置还是改源站。

先判断该绕缓存还是该留缓存

选择依据是你要回答的问题不同。如果你要判断“这个链接到底死没死”,就必须让请求绕过 CDN、反向代理和页面缓存,直接打到源站,否则你测的是缓存副本的存续状态,不是源站的真实响应。如果你要判断“用户点开这个链接会看到什么”,就必须保留完整缓存链路,因为用户命中的正是这条路径。

两种做法的代价不一样。绕过缓存能拿到干净结论,但会掩盖真实的用户侧故障,也可能因为直连源站触发限流或防护策略,让结果失真。保留缓存贴近真实,但同一 URL 在不同节点、不同时间可能返回不同版本,你需要接受结果本身带噪声,并靠多次采样和对照来收敛,而不是指望一次扫描给出一致答案。

适用条件是:只有当源站和缓存链路都受你控制、或至少能分别观测时,这个拆分才有意义。如果缓存由第三方托管且无法指定绕过参数,你只能退而用带随机查询串的请求做近似直连,并明确这只是一个假设性的近似,不代表源站一定被正确回源。

用同一个探针 URL 逐层剥离

具体动作是选一个已知会返回固定状态的 URL 作为探针,比如一个确定存在的页面和一个确定不存在的路径,然后按层剥离,每剥一层记录一次响应状态和响应头中的缓存标记。

  1. 完整链路请求一次,记录状态码、缓存命中标记和返回内容的版本特征(例如某个只在特定版本出现的字符串)。
  2. 只绕过最外层 CDN,保留源站前置的反向代理,再请求一次,对比是否与完整链路一致。
  3. 继续绕过反向代理,直连应用或源站,再请求一次。
  4. 把三次结果并列。哪一层开始出现分歧,问题就落在那一层及其回源规则上。

这个动作的结果直接决定下一步:如果分歧出现在最外层,优先查该层的缓存键是否包含了不该包含的维度(如 Cookie、设备标识),或者过期时间是否过长;如果分歧出现在反向代理层,查它的缓存规则是否把带参数的请求和不带参数的请求当成同一个键;如果直连源站就已经不一致,那和缓存无关,回到应用或数据层排查。

区分几种常见的分歧原因

同一 URL 返回不同版本,通常不是单一原因。可以用下面的证据组合来区分,而不是看到不一致就归咎于缓存:

这里要提醒一个容易踩的坑:请求量、抓取量或某个状态计数归零,不能单独证明你的处理是对的。它也可能只是缓存整体过期、检测任务被限流、或探针 URL 恰好被临时屏蔽。要结合直连结果和响应头一起看。

一个假设性的短例子

假设某页面在源站返回 200,但通过 CDN 访问时,一部分请求返回 404。按上面的方法,先直连源站确认 200 稳定,再保留 CDN 但固定查询串复测,发现带某个参数时 404、不带时 200。此时可以推断 CDN 把带参数的请求当成了独立的缓存键,而该键下缓存了一个旧的 404 副本。下一步动作是清理该键或调整缓存规则,让带参数的请求正确回源;改完之后再用同样的探针复测两类请求,确认分歧消失,而不是直接宣布问题解决。

反过来,如果直连源站本身就间歇性 404,那清理缓存只会让问题更快暴露,正确动作是回到源站排查路由或数据,缓存层无需改动。这也是为什么必须先做直连对照,再决定动哪一层。

例外与边界

有一种情况上述拆分不成立:当缓存层和源站由不同团队维护,且你无法获得直连权限时,你只能用带随机参数的请求做近似,并把结论标注为“未验证源站”。此时不要断言源站状态,只报告缓存链路的表现,并把需要对方核实的部分明确列出。

另外,robots.txt 的抓取限制不等于可靠的索引移除,站点地图也不保证收录,这些和缓存一致性是两个层面的问题,不要混在一次排查里下结论。定位缓存分歧时,只关注响应状态、响应头和版本特征这三类可观测证据,避免把抓取策略问题误判成死链。

图1 图2

nginx