当同一个 URL 在不同网络、不同设备或不同请求头下,一会儿返回 404、一会儿返回 200,通常不是“404 的含义变了”,而是请求路径上至少有一层缓存保存了不同状态。要定位一致性问题,先要区分两种解释:一种是被请求资源本身确实不存在,404 是源站真实响应;另一种是资源存在,但某一层缓存把旧的 404 或旧的 200 固定下来,后续请求命中了不同副本。能区分这两者的关键证据,是响应头里的缓存相关字段、各层缓存的命中标识,以及绕过缓存后的源站响应是否稳定。
404 表示服务器收到了请求,但找不到对应资源。它和“请求根本没到达源站”是两回事。多层缓存下常见的矛盾是:边缘节点返回 404,回源却返回 200;或者带某个 Cookie、某个 Accept 头时返回 404,去掉后又返回 200。此时不要急着改页面内容,而要先判断 404 是源站生成后缓存下来的,还是某一层缓存自己生成的。源站生成的 404 通常带有站点统一的错误页特征,缓存生成的 404 可能缺少这些特征,并带有该层自己的标识头。
解释一:源站对同一路径返回了不同状态。例如源站根据 User-Agent、语言、登录态或后端灰度,把部分请求路由到没有该资源的服务,于是真实返回 404。这种情况下,绕过所有缓存直接请求源站,仍会看到状态随条件变化。
解释二:源站状态一致,但缓存副本不一致。例如源站后来恢复了资源并返回 200,但某些边缘节点或中间代理仍保留早先的 404;或者源站返回 200 时缺少明确的缓存指令,不同层按各自默认策略缓存了不同版本。这种情况下,直接请求源站会稳定返回同一个状态,而经过缓存链路时状态随节点变化。
两种解释都会表现为“同一 URL 有时 404 有时 200”,但处理方向完全相反:前者要修源站路由或资源发布逻辑,后者要修缓存键、缓存指令或清理策略。
可以按下面的顺序收集证据,每一步的结果都会决定下一步查哪里:
假设一个场景:某路径在 A 网络返回 404,在 B 网络返回 200,源站直连始终返回 200。此时可以先用 curl -I 对比两边的响应头,若 A 网络的响应带有较高的缓存年龄且没有源站标记,而 B 网络带有源站标记,那么优先怀疑 A 路径上的缓存节点保留了旧 404。这个判断只是缩小范围,仍需用源站日志确认 404 不是源站间歇性产生。
如果证据指向缓存副本不一致,直接清缓存往往只能短暂恢复,因为下一次请求仍可能按同样的规则缓存出不同版本。实际动作是:先确认缓存键包含哪些维度,是否把 Cookie、语言、设备类型或查询参数纳入键;再确认源站对 200 和 404 分别返回了什么缓存指令。若 404 被允许长时间缓存,而资源恢复后没有主动失效,旧 404 就会持续存在。
一个可执行的调整是:对确实不存在的路径返回 404 时,附带较短的缓存时间或不缓存;对恢复后的 200 响应,确保缓存指令允许更新,并在发布流程中触发对应缓存键的失效。做完这一步后,重新用多网络、多请求头采样,观察状态是否收敛到同一版本。如果仍不收敛,说明缓存键维度或中间层策略还没对齐,需要继续查下一层。
请求量下降、抓取量归零或某个节点返回 404,都不能单独证明处理正确。它们还可能来自采集延迟、日志采样、节点切换或客户端重试。定位一致性问题的可靠做法,是把源站响应、各层缓存标识、请求头差异和时间窗口放在一起对照。只有能解释“为什么同一路径在不同条件下得到不同状态”,才算真正定位到问题层。