记录一下那天晚上的排查过程。日志里蜘蛛的请求状态码全是 200,但 body_bytes_sent 那一列大量为 0,GSC 快照打开是空白页,用浏览器访问同样的地址却能看到完整正文。
刚开始盯着「gzip 过滤模块在压缩阶段出错,响应被截断成空」,折腾了半个多小时,排掉了。
原因不止一个,得分开看。上游返回了空响应体,Nginx 只转发了响应头。少数情况下是页面走了 304 分支,日志按 200 记录但实际没有内容。
还有一种情况,后端 PHP 触发致命错误但 display_errors 关闭,输出为空。
上来先按字节数为 0 的占比做统计
awk '$9==200 && $10==0{print $7}' access.log | sort | uniq -c | sort -rn | head
带蜘蛛 UA 复现并看完整响应头
curl -sI -A 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)' https://www.example.com/a/1.html
接着关闭压缩后再取一次正文长度
curl -s -H 'Accept-Encoding: identity' https://www.example.com/a/1.html | wc -c
剩下的就是检查应用错误日志里同一时间的记录
grep -i 'PHP Fatal' /var/log/php/error.log | tail -20
改完先别撤,确认这几项。关闭出错的压缩模块后,字节数为 0 的记录从每天上千条降到个位数,抓取快照能正常渲染正文。
200 只说明请求被受理,字节数为 0 的 200 对蜘蛛来说和打不开一样,统计抓取健康度要把这一列带上。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。
