$upstream_addr精确记录Nginx实际连接的后端地址(格式为IP:Port),可验证负载均衡真实落地节点;配合map映射、响应头透传及$upstream_status序列分析,能准确定位调度偏差、健康检查误摘或重试绕过等问题。

直接看 $upstream_addr 的值,再比对你的 upstream 配置和路由策略,就能确认请求是否真落到了预期节点——它不是配置里写的“可能”,而是 Nginx 实际连上的“已经发生”。
核对 $upstream_addr 是否匹配预期后端地址
该变量输出格式为 IP:Port(如 10.0.1.12:8080),包含端口信息,能区分同一主机上多个服务实例。若你期望某次请求打到 be-c 节点(对应 10.0.1.12:8080),日志中出现该地址即表示命中。
- 若始终未出现预期地址,说明负载策略未生效:检查是否用了 hash、ip_hash 或 consistent_hash 等定向算法,且 key(如 $request_id)是否稳定
- 若预期地址只零星出现,而其他地址高频出现,可能是权重设置偏差、健康检查误摘除,或重试机制覆盖了原始调度
- 若日志中该字段为空,说明请求根本没走 proxy_pass(比如被 rewrite 截断、匹配了 return 或静态文件规则)
结合重试行为验证“最终落地”是否符合预期
启用 proxy_next_upstream 后,$upstream_addr 会以逗号分隔记录完整路径(如 10.0.1.10:8080, 10.0.1.12:8080)。最后一个是真正返回响应的节点,也就是“最终落地”的地址。
- 关注逗号后的最后一个地址,它才是实际处理请求的后端
- 若你希望请求始终由
be-c处理,但日志中大量显示..., 10.0.1.11:8080,说明be-c可能持续失败,已被自动绕过 - 对比
$upstream_status序列(如502,200)可确认前序节点是否真的不可用
用请求头透传辅助交叉验证
仅靠日志字段有时不够直观,可在响应头中主动透出后端标识,与 $upstream_addr 对齐验证:
- 在 upstream 块中为每台机器设唯一 id:
server 10.0.1.12:8080 id=be-c; - 用 map 将 $upstream_addr 映射为可读 ID:
map $upstream_addr $backend_id { ~10\.0\.1\.12:8080 "be-c"; ... } - 通过
proxy_set_header X-Backend-ID $backend_id透传给客户端或下游系统 - 收到响应后比对
X-Backend-ID和日志中的 $upstream_addr,二者一致才说明链路未错位
排查常见不一致原因
当 $upstream_addr 显示的地址与预期不符,优先检查以下几项:
- upstream 配置是否用了域名而非 IP:DNS 解析结果可能变化,导致 $upstream_addr 显示的是解析后的具体 IP,而非你记忆中的“固定地址”
- 是否启用了
least_conn或random等动态策略,而你误以为是轮询 - 后端是否设置了
proxy_cache_bypass或proxy_no_cache,导致部分请求跳过缓存直连,触发不同路径 - Nginx 版本是否低于 1.7.5:旧版本对 $upstream_addr 的填充逻辑不完善,尤其在重试场景下可能丢失中间地址


















