CDN 默认缓存所有 GET 请求,A 用户搜 nginx,B 用户搜 mysql 时看到上一次的结果,GSC 抓到的搜索页内容也互相对不上。
一开始怀疑是「Vary 头缺失,不同查询串共用一份缓存」,查了一圈,方向不对。
排查方向其实有限,先把可能性排一排。CDN 缓存键没有包含查询参数。少数情况下是源站没给搜索页发 no-store。
少数情况下是爬虫拿到别人搜索结果的缓存副本,内容与 URL 不符。
上来先确认响应头里的缓存策略
curl -sI 'https://www.example.com/?s=nginx' | grep -i 'cache-control\|x-cache'
源站给搜索页禁用缓存
add_action('template_redirect', function(){ if(is_search()){ header('Cache-Control: no-store, private'); } });
CDN 侧绕过带 s 参数的请求
curl -X PUT https://api.cdn.example.com/rules -d '{"path":"/?s=*","cache":"bypass"}'
剩下的就是验证不同查询串返回不同内容
for k in nginx mysql redis; do curl -s "https://www.example.com/?s=$k" | grep -o '<title>[^<]*</title>'; done
那几天正好在做别的变更,先把时间线对齐才敢动手。
别只看报错消失,验证要多做一步。三个查询串返回三种不同标题,响应头里带 no-store,x-cache 显示 BYPASS。
容易忽略的是,搜索页缓存能省回源,但串号带来的错误内容比性能损失严重,宁可全部绕过。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。
