现场是这样的。CDN 缓存键把尾斜杠归一化掉了,/list 和 /list/ 被当成同一个地址,两套 HTML 互相覆盖,蜘蛛抓 /list/ 时偶尔拿到另一版,canonical 也跟着变。

中间走过弯路,把「没有用 301 统一尾斜杠」当成主因,改完现象没变。

真正麻烦的地方在于,几个原因的现象几乎一样。缓存键把尾斜杠归一化掉了;源站两个地址返回的内容不同;Vary 头没有覆盖到地址差异。

先确认两个地址返回是否一致

curl -s https://www.example.com/list -o a.html; curl -s https://www.example.com/list/ -o b.html; Compare-Object (Get-Content a.html) (Get-Content b.html)

随后统一 301 到带斜杠版本

location = /list { return 301 /list/; }

缓存键保留原始 URI

proxy_cache_key "$scheme$host$request_uri";

剩下的就是清掉旧缓存复核

curl -X PURGE https://www.example.com/list/

报错是间歇性的,我蹲守了半小时才抓到一次完整现场。

白天有业务在跑,能验证的部分都压到了晚上做。

当时还开着另一个排查窗口,两边日志对照着看才定位到。

恢复的判定其实很直接。/list 301 到 /list/,边缘缓存不再混用两份 HTML,canonical 稳定下来。

缓存键一旦归一化,尾斜杠、大小写、参数顺序的差异都会被抹平。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。

作者 9823189