关键在于对齐日志变量、作用域与后端配置:http代理需在启用proxy_pass的location中使用$upstream_*变量并自定义log_format;tcp/udp代理须在独立stream块中配置专用日志格式。

要在 Nginx 负载均衡中准确记录后端状态与转发明细,关键不是开启某个开关,而是把日志变量、作用域和后端配合三者对齐。默认 access_log 完全不体现 upstream 行为,必须主动配置才能看到“到底转给了谁、耗时多少、返回什么状态”。
用对变量:HTTP 代理必须用 $upstream_* 系列
这些变量只在 启用了 proxy_pass 的 location 或 server 块内有效,且仅限于 HTTP 上下文(http 块):
-
$upstream_addr:实际连接的后端地址,如
10.0.1.10:8080;失败重试会显示多个,用逗号分隔 - $upstream_status:对应每个地址的响应状态码,顺序与 $upstream_addr 严格一致
- $upstream_response_time:Nginx 等待该后端响应的时间(秒,精度毫秒)
- $upstream_connect_time:建立 TCP 连接耗时,可识别网络层延迟
- $upstream_header_time:从连接建立到收到后端响应头的时间
定义并启用自定义日志格式
在 http 块顶部添加 log_format,例如:
log_format upstream_log '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent
"$http_referer" "$http_user_agent"
upstream: $upstream_addr
upstream_status: $upstream_status
upstream_response_time: $upstream_response_time
upstream_connect_time: $upstream_connect_time
request_id: $request_id';
然后在具体 location 中启用:
location /api/ {
proxy_pass http://backend;
access_log /var/log/nginx/upstream.log upstream_log;
}
⚠️ 注意:如果该 location 没有 proxy_pass,所有 $upstream_* 变量值都是空字符串或“-”。
让后端返回可追踪标识
单靠 Nginx 日志无法区分是哪个业务实例处理了请求。建议后端在响应头中带上唯一标识:
- 返回
X-Backend-ID: app-v2-03或X-Process-Time: 42.6ms - Nginx 可通过
$upstream_http_x_backend_id和$upstream_http_x_process_time写入日志 - 这样就能把 Nginx 调度日志和后端处理日志按标识关联起来,做链路分析
TCP/UDP 代理需用 stream 块单独配置
MySQL、Redis 等透传场景不走 HTTP,必须在 独立的 stream 块 中配置:
stream {
log_format tcp_log '$remote_addr:$remote_port - [$time_local] $status $protocol
"$upstream_addr" $upstream_connect_time $upstream_bytes_sent';
access_log /var/log/nginx/tcp_access.log tcp_log;
upstream db_cluster { server 10.0.2.5:3306; server 10.0.2.6:3306; }
server { listen 3306; proxy_pass db_cluster; }
}
stream 块中的变量(如 $upstream_connect_time)与 http 块互不兼容,混用会导致日志字段为空。











