现场是这样的。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 稳定下来。
缓存键一旦归一化,尾斜杠、大小写、参数顺序的差异都会被抹平。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。
