先给结论:当缓存层把一个错误页面连同 200 OK 一起返回时,不能只凭浏览器看到“正常打开”就认定缓存没问题,也不能只凭回源日志里出现过一次错误就认定整层缓存已污染。可操作的核对方式是固定同一 URL、同一请求头,分别观察缓存层与源站的状态码、响应头和正文特征,再判断不一致发生在哪一层。
假设一个页面在源站因模板异常生成了“内容不存在”的提示,但源站自身返回的是 200 OK,缓存层只是忠实地把这个响应存了下来。这种情况下,缓存并没有“改状态码”,它复制的是源站给出的状态。反过来,源站返回 404 或 500,而缓存层因为配置、错误页替换或边缘逻辑,把它包装成 200 再发给客户端,这才是缓存层引入的状态不一致。
两种解释对应的修复动作完全不同:前者要改源站错误处理,后者要改缓存策略。所以第一步不是清缓存,而是先确认“错误状态码是在哪一层消失的”。
能区分上述两种解释的证据,核心是“绕过缓存后状态码是否改变”。可以按下面的顺序取证据:
Age、Cache-Control、Vary 以及可能的缓存命中标识。如果绕过缓存返回 404,经过缓存返回 200,并且正文是同一个错误页指纹,那么不一致发生在缓存层。如果两次都返回 200 且正文相同,问题在源站,缓存只是放大或延长了它。
这里有一个容易误判的点:回源日志里出现 404 只能说明源站曾对某次请求返回过该状态,不能单独证明当前缓存里存的就是这个 404。同样,缓存命中率突然升高或某段时间抓取量归零,也不能单独证明状态码处理正确,它们还可能是请求减少、规则调整或统计口径变化造成的。
多个角色对“页面是否正常”有不同理解时,分歧往往来自各自看的层不同:前端看渲染结果,运维看回源日志,SEO 看抓取响应。要把它转成可核对的项目,需要固定以下变量,再逐项记录结果:
Accept、User-Agent 和可能触发 Vary 的字段。一个短例子(假设):某详情页在源站因数据缺失返回 404,缓存层却按“错误页也缓存”的规则存成 200。核对时绕过缓存得到 404 加错误页指纹,经过缓存得到 200 加同一指纹,即可判定缓存层把错误状态改写了。下一步就不是继续查源站模板,而是调整缓存对非 2xx 响应的处理规则,并复查同规则下还有哪些 URL 受影响。
如果证据指向缓存层,先确认受影响范围再改规则:用同一缓存规则、同一内容指纹去抽样其他 URL,看是个例还是成片。只清一个 URL 的缓存,通常只能让当前页面恢复,不能阻止下一次错误页再次被存成 200;改规则能阻止复发,但需要确认新规则不会误伤正常页面的缓存效率。
如果证据指向源站,缓存层不需要大改,重点转到源站的错误处理:让内容缺失时返回 404 或 410,让服务异常时返回 5xx,并保证错误页正文与状态码语义一致。改完之后,仍需按上面的固定变量再核对一次,确认经过缓存与绕过缓存得到的状态码和正文指纹已经一致。若涉及 robots.txt、站点地图或 HTTPS 相关判断,它们各自的作用边界不同,不能替代这次状态码与内容一致性的核对。