应使用$upstream_status变量记录上游服务器返回的真实HTTP状态码,该变量在Nginx≥1.7.10中稳定支持,多个upstream时以逗号分隔,未转发时显示为“-”。

要让 Nginx 日志准确记录后端 Upstream 服务器返回的真实 HTTP 状态码(即上游实际响应的状态码,而非 Nginx 自身生成的如 502、503 等代理层状态码),关键在于使用 $upstream_status 变量,并确保它在日志格式中被正确引用、且 Nginx 配置逻辑不会覆盖或干扰其取值。
确认 $upstream_status 的行为特点
$upstream_status 是 Nginx 内置变量,表示与当前请求匹配的 upstream server 实际返回的 HTTP 状态码。它的取值有以下要点:
- 仅在成功从 upstream 接收到响应时才有意义;若连接失败(如超时、拒绝连接)、Nginx 自行返回错误(如 502/504),该变量值为 “-” 或空字符串
- 当启用
proxy_next_upstream并发生重试时,$upstream_status记录的是**最终成功响应的那个 upstream 的状态码**,不是第一次失败的 - 它不等于
$status(Nginx 发送给客户端的响应状态码),后者可能被 error_page、rewrite 或内部跳转修改
定义含 $upstream_status 的自定义日志格式
在 http 块中定义日志格式,显式包含 $upstream_status:
log_format upstream_log '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'upstream_addr:$upstream_addr '
'upstream_status:$upstream_status '
'request_time:$request_time '
'upstream_response_time:$upstream_response_time';注意:$upstream_status 在无 upstream 响应时会输出“-”,这是正常行为,可用于识别失败场景。
确保 upstream 配置和 proxy 设置不干扰状态码传递
以下配置要点可避免 $upstream_status 失效或失真:
- 不要用
error_page 502 503 504 = @fallback类重写方式掩盖原始 upstream 状态 —— 这会导致$upstream_status无法记录(因未真正收到 upstream 响应) - 如需容错,建议用
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;触发重试,这样仍能捕获最终成功节点的状态码 - 禁用
proxy_intercept_errors on(默认 off),否则 Nginx 可能拦截并替换 upstream 的错误响应,导致$upstream_status不再反映真实值
验证日志输出是否符合预期
通过 curl 或压测工具发起请求,同时查看 access log 输出:
- 后端返回 200 → 日志中
upstream_status:200,status:200 - 后端返回 500 → 日志中
upstream_status:500,status:500(前提是未配 error_page 拦截) - 后端宕机触发 502 → 日志中
upstream_status:-,status:502 - 启用重试后某节点返回 200 →
upstream_status:200,即使第一个节点返回了 503
可配合 tail -f /path/to/access.log | grep upstream_status 实时观察。











