先接受一个前提:多层缓存下,同一个自定义404错误页出现不同版本,通常不是页面文件本身出错,而是不同缓存层对同一请求给出了不同响应。要定位一致性问题,最有效的做法不是逐层清缓存,而是先固定一个可复现的请求,记录每层返回的状态码、响应头和页面片段,再判断该保留哪一版、改写哪一版、退出哪一版。
多个角色对同一个404页面的理解不同,往往因为各自看到的请求路径、设备、地区或登录状态不一样。此时先把分歧转成一条可核对的记录:完整URL、请求方法、请求头中的Accept与Cookie、时间戳,以及每层缓存的响应。
需要记录的字段至少包括:HTTP状态码、Content-Type、Content-Length、Cache-Control、Age、ETag或Last-Modified、Vary,以及页面中一段稳定文本。假设一个例子:同一个不存在的路径,在浏览器里看到的是带搜索框的404页,在命令行请求时返回的是纯文本“Not Found”。这并不能直接说明哪层缓存坏了,只能说明两层的响应内容不同,需要继续看状态码和Vary头。
动作上,先选一条请求,分别从客户端、CDN边缘、反向代理和源站各取一次响应。结果如何影响下一步:如果四层状态码一致但页面片段不同,问题在缓存键或内容协商;如果状态码本身就不一致,问题在某一层是否把404改写成了200或302。
定位到差异层之后,处理方式不是统一的。可以按下面的条件做取舍。
这三种取舍可以并存于不同层。例如边缘层保留缓存,代理层改写状态码,源站退出对404页的额外包装。关键不是选一个全局答案,而是让每层的行为与它承担的角色一致。
自定义404错误页的常见异常是:页面看起来是404,但返回状态码是200;或者状态码是404,但页面内容被替换成了首页。这两种情况的排查方向不同。
如果状态码是200,先检查该层是否配置了“软404”或回退到首页的规则。此时页面不一致只是结果,根因是状态码被改写。如果状态码是404但内容不同,重点看Vary头和缓存键:是否按User-Agent、Accept-Language或Cookie分了不同版本,而某一层没有正确携带这些维度。
一个可操作的动作是:临时移除某一层的缓存,再请求同一路径。结果如何影响下一步:如果移除后所有层一致,说明问题在该层的缓存键;如果仍不一致,说明差异在更靠近源站的位置,需要继续往上游查。
多角色协作时,最容易卡在“都觉得自己看到的是对的”。把分歧转成项目,需要明确三件事:哪一层负责、改什么、用什么请求验证。
验证时不要只看“页面是否正常显示”。更可靠的依据是状态码、Content-Type和一段稳定文本是否在四层一致。如果只有某一层不一致,就回到该层继续查;如果全部一致,再观察一段时间,确认没有其他路径触发同类差异。
请求量下降、抓取量归零或监控里404数量突然减少,都不能单独证明处理正确。它们还可能是抓取工具暂时减少、日志采样变化、监控规则调整或路径本身不再被访问。要结合同一请求的多层响应来判断。
另外,robots.txt的抓取限制不等于可靠的索引移除,站点地图也不保证收录。自定义404页的一致性问题应聚焦在响应本身,而不是用这些信号替代排查。不同搜索引擎对404状态码和软404的处理方式需要分别核查,不能假设一套配置对所有抓取方都产生相同结果。
最后,如果某一层缓存返回的版本虽然不同,但状态码正确、内容对用户可用,且差异只体现在缓存元数据上,可以暂时保留并记录,不必为了“完全一致”而反复清缓存。定位一致性问题的终点,是让每层的行为可解释、可复核,而不是让所有层在任何时刻都返回逐字节相同的响应。