nginx 自定义日志中输出所有重试后端 ip 链需使用 $upstream_addr 变量,它在请求结束时记录完整转发路径(如 10.0.1.10:8000, 10.0.1.11:8000),配合 proxy_next_upstream 配置生效,且必须通过 upstream 块定义后端。

要在 Nginx 自定义日志格式中输出所有参与重试的后端 IP 链,核心是利用 $upstream_addr 变量——它天然记录了本次请求实际经过的所有 upstream server 地址(含重试路径),以逗号分隔。
理解 $upstream_addr 的行为
$upstream_addr 不是单个 IP,而是完整调用链快照:包括首次转发地址、每次重试的新地址,以及连接阶段的 UNIX 域套接字或端口信息。例如:
若未重试,则只含一个地址;若发生两次重试,就含三个地址。该变量在请求结束时才完全确定,因此可安全用于 access_log。
定义支持重试链的日志格式
在 http 块中定义 log_format,直接引用 $upstream_addr:
log_format upstream_chain '[$time_local] $remote_addr "$request" '
'$status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'upstream="$upstream_addr" '
'rt=$request_time uct=$upstream_connect_time '
'uht=$upstream_header_time utt=$upstream_response_time';
注意:$upstream_addr 已包含所有重试节点,无需额外拼接或脚本解析。
确保重试机制被触发且可记录
- 确认配置了
proxy_next_upstream(如error timeout http_500),否则不会重试,$upstream_addr永远只含一个地址 - 避免使用
keepalive连接池导致地址复用混淆——Nginx 仍会如实记录每次实际选择的 server 地址 - 若用
upstream_hash或least_conn等负载策略,重试链依然有效,$upstream_addr按实际转发顺序记录
排查常见空值或截断问题
$upstream_addr 在以下情况为空或不完整:
- 请求未进入 upstream(如匹配到 location 但没 proxy_pass)→ 日志中该项为短横线
- - 使用了
proxy_pass到非 upstream 块(如直接写死域名或 IP)→ 此时$upstream_addr不生效,应改用upstream块定义后端 - 日志行过长被截断 → 检查
log_format中字段总长,必要时精简其他字段(如去掉$http_user_agent)











