这类问题我又碰上了一次。CentOS 7.9 的站点用 error_page 把 502 和 504 统一跳到静态页,监控按 access.log 的 $status 统计,线上已经有一批接口挂了,告警面板上一个红点都没有。
第一反应是「监控采集的是页面返回码,不看 upstream_status」,验证下来不成立。
原因不止一个,得分开看。error_page 做了内部跳转,返回给客户端的状态码变成了 200;error_page 没加 = 保留原状态码的语法,日志里记的是跳转后的结果;静态兜底页本身也 200,把连续失败伪装成了正常访问。
动手时先看日志里 upstream_status 的真实值
awk '{print $9,$10}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
日志格式里补上上游状态
printf 'log_format up \'$remote_addr $status $upstream_status $upstream_addr\';\n' > /etc/nginx/conf.d/log.conf
error_page 用 = 保留原始状态码
sed -i 's#error_page 502 /50x.html#error_page 502 =502 /50x.html#' /etc/nginx/conf.d/site.conf
末了确认返回码已经恢复
curl -sI http://127.0.0.1/api/health | head -1 && nginx -s reload
怎么算真的好了,看的是同一批现象。curl 访问失败的接口能拿到 502 而不是 200,access.log 里 $upstream_status 与 $status 一致,监控曲线能反映出真实的失败率。
error_page 不加等号时默认返回 200,这是最容易被漏掉的一处;监控最好同时采 upstream_status,否则兜底页会把故障藏起来。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。
