先确认一个前提:你看到的是同一URL在不同层返回不同结果——有的层返回404,有的层返回200。这通常不是源站真的删了页面,而是各层缓存的键、过期时间或刷新方式不一致。最有效的动作是固定一个请求标识(如带唯一查询参数的URL或自定义请求头),从最外层向内逐层请求并记录每层的状态码与缓存命中标记,找出第一层开始返回404的位置,再针对那一层检查缓存键规则和清除机制。
多层缓存下最容易犯的错,是外层测的是带参数的URL,内层测的是不带参数的URL,结果自然不同。你需要先选定一个具体页面URL,然后为它建立一份对照记录,至少包含:请求的完整URL、请求头中的缓存相关字段、每层返回的状态码、以及该层是否命中缓存的标记(如 X-Cache、Age、CF-Cache-Status 这类响应头,具体名称取决于你使用的缓存软件)。
如果各层对查询参数的处理不同——比如CDN默认忽略某些参数、而反向代理不忽略——那么同一个页面在CDN层可能命中200的旧副本,在代理层却因为参数变化回源拿到404。这时你测出的“不一致”其实是缓存键不一致,而不是源站状态不一致。
不要同时清所有缓存,那样会丢失判断依据。按下面的顺序做:
关键判断:如果源站返回200,但最外层返回404,而中间层返回200,说明分叉发生在最外层到中间层之间。此时应检查最外层的缓存键是否包含了中间层不包含的变量(如某个请求头、协议版本、Host写法)。
缓存键不一致:表现为同一URL在不同层命中不同对象。证据是两层的缓存命中标记指向不同缓存条目,或带与不带某参数时状态码跳变。处理动作是统一各层的缓存键规则,或在源站对参数做归一化处理。
过期时间与刷新机制不一致:表现为一段时间内一致,过一段时间后某层先过期回源拿到404,另一层还在提供旧副本。证据是各层响应头中的 Age 或过期时间字段差异明显。处理动作是让各层的TTL策略对齐,或对404响应设置较短的缓存时间,避免错误状态被长期缓存。
清除操作只作用于部分层:表现为手动清除后外层恢复了200,但内层仍是404,或反之。证据是清除前后逐层请求的状态码变化只出现在部分层。处理动作是建立覆盖所有层的清除流程,并在清除后按同样顺序复测。
需要说明的是,某个层抓取量或请求量归零,并不能单独证明该层已经正确清除了404缓存——它也可能是该层根本没有收到请求,或请求被上层拦截。要结合逐层请求的返回结果判断。
假设你有一个页面 /guide,源站返回200。CDN返回404,反向代理返回200。你带一个随机查询参数 ?v=1 请求CDN,发现返回200。这说明CDN的缓存键忽略了查询参数,命中了另一个缓存条目,而该条目对应的旧副本恰好是404。此时你的下一步不是去源站改内容,而是检查CDN的缓存键配置,确认它是否应该忽略查询参数;如果应该忽略,就需要清除CDN上该URL对应的错误缓存条目,并调整404响应的缓存策略,防止再次被缓存。
这个例子的价值在于:它把“多层不一致”缩小到了“某一层的缓存键规则”这一个可修改的配置项上,而不是让你在四五个系统之间反复试错。
找到分叉层之后,处理动作应当只针对该层,并在修改后按同样的逐层顺序复测。复测时重点看两件事:第一,之前返回404的那一层现在是否返回与源站一致的状态码;第二,该层的缓存命中标记是否指向了正确的缓存条目。如果复测通过,再把同样的检查方法扩展到同类型的其他URL上,确认不是单页特例。若复测后仍然不一致,说明还有一层未被纳入观察范围,需要继续向内或向外扩展请求链路。