应记录 $upstream_status 而非 $status,因其准确反映后端真实响应状态;需自定义日志格式、按 upstream_addr 和 upstream_status 聚合分析,并通过 nginxlog-exporter 接入 prometheus 实现告警闭环。

在微服务网关场景中,Nginx 本身不生成业务状态码,但它是所有请求的统一入口,能准确捕获并区分“客户端看到的状态码”($status)和“后端真实返回的状态码”($upstream_status)。要监控全局状态码指标,关键不是看 Nginx 自己返回了什么,而是聚焦上游服务的真实响应质量。
必须记录 $upstream_status 而非 $status
Nginx 默认 access log 中的 $status 是它返回给浏览器或客户端的状态码。比如后端返回 500,而 Nginx 配了 error_page 500 =200 /fallback.html,日志里就只记 200 —— 这会掩盖真实故障。真正反映微服务健康状况的是 $upstream_status,它记录 Nginx 从每个 upstream 实例收到的原始响应码。
- 在
http块中定义专用日志格式,显式包含该字段:
log_format upstream_log '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "upstream:$upstream_addr" "upstream_status:$upstream_status" "upstream_response_time:$upstream_response_time" "request_time:$request_time';
- 在对应 server 或 location 中启用:
access_log /var/log/nginx/upstream.log upstream_log; - 注意:
$upstream_status在连接失败、超时或未转发时显示为-,这是有效信号,代表“无响应”,需单独统计
按服务与实例维度聚合分析
微服务通常有多个实例(如 api-v1-01、api-v1-02),单看总错误率没意义。应把日志按 upstream_addr 和 upstream_status 两字段联合提取,定位异常节点。
- 快速查看各实例 5xx 分布(假设日志第9列为
upstream_addr,第10列为upstream_status):
awk ' ~ /^[5]/ {print , }' /var/log/nginx/upstream.log | sort | uniq -c | sort -nr
- 统计某服务(如
backend-auth)最近 1 分钟内 500 比例是否突增,可配合tail -f+awk流式计算,或接入 Telegraf + InfluxDB 做滚动窗口统计 - 避免用
$upstream_http_status:它依赖后端显式设置Status响应头,可靠性远低于$upstream_status
识别“假成功”与重试干扰
有些请求看似成功,实则后端已出错。常见于以下配置:
-
proxy_intercept_errors on;+error_page 500 =200 /custom.html:导致$upstream_status被覆盖或丢失 -
proxy_next_upstream开启后,一次请求可能触发多次回源,$upstream_status会是逗号分隔值(如"502,200"),需拆分后取最终成功码
建议保持 proxy_intercept_errors off(默认值),关闭自定义错误页重写;对关键服务启用 proxy_next_upstream error timeout http_500 http_502 http_503 http_504;,让失败自动重试,同时保留最终响应的真实状态。
对接 Prometheus 实现告警闭环
单纯看日志不够及时。推荐用 nginxlog-exporter 解析 upstream.log,将每条日志转为指标,例如:
nginx_upstream_status_count{code="502", host="auth-service", addr="10.0.1.12:8080"} 1
- 在 Prometheus 中定义规则:过去 3 分钟内,
code="5xx"占比 > 3% 且持续 2 个采样周期,触发告警 - Grafana 中按
host标签分组仪表盘,一眼看清哪个微服务、哪台实例状态异常 - 结合 systemd 的
HealthCheckIntervalSec=30,对 Nginx 进程做存活探活,补全日志与指标之外的兜底层











