加权轮询日志分析必须以 $upstream_addr 为唯一依据,需确认其在 log_format 中显式定义、正确启用,并过滤异常值;提取后应结合健康检查、stub_status 和分离日志交叉验证实际分发。

排查加权轮询日志分析中字段提取错误,核心是确认 $upstream_addr 是否被正确记录、解析和过滤——它才是验证权重是否真实生效的唯一可靠依据,其他字段(如 upstream 名称、配置顺序)无法反映实际转发行为。
检查 log_format 是否包含 $upstream_addr 且位置准确
很多提取失败源于日志格式本身没记录该变量:
- 必须在
log_format中显式写入$upstream_addr,不能依赖默认格式;示例:log_format main '$remote_addr - [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_time $upstream_response_time $upstream_addr'; - 确保该
log_format已在对应server或location块中通过access_log启用,而非仅定义未使用 - 注意:$upstream_addr 只在请求真正进入 upstream 模块后才有值;若请求被限流、deny、SSL 握手失败或直接返回 499/503,该字段会显示为
-或空,需提前识别这类非转发场景
验证 $upstream_addr 值是否符合预期格式
提取脚本常因地址格式不一致而漏匹配:
- $upstream_addr 记录的是 IP:Port(如
10.0.1.10:8080),不是 upstream 名称(如backend_cluster),也不是无端口 IP - 若后端启用了 keepalive 连接复用,同一连接可能多次复用相同 $upstream_addr,但日志中仍逐行记录,不影响统计逻辑
- 常见异常值必须过滤:
-(未转发)、*(重试失败标记)、none(未命中 upstream)、含空格或换行的脏数据;建议用grep -v '[-* ]'或awk '$NF !~ /^[-*]$/ {print $NF}'预处理
比对日志提取结果与理论权重比例是否合理偏离
即使字段提取正确,结果“看起来不对”也可能是正常现象,需区分真错误与合理偏差:
- 加权轮询不是严格按秒级比例分配,而是基于请求序列的动态调度;短期(如1分钟)统计波动大属正常,应观察 5–15 分钟窗口
- 若某节点实际占比远低于理论值(如 weight=5 的节点只占 20%),先查它是否被健康检查临时剔除:
tail -100 /var/log/nginx/error.log | grep "fail_timeout\|unhealthy" - 用
curl -s http://localhost/stub_status查看 upstream 实时状态,确认各 server 的Active连接数和State(如down或unavail) - 若所有节点都 active,但分布仍严重倾斜,再回查是否误配了
ip_hash或least_conn等覆盖策略
用独立节点日志交叉验证真实分发
全局日志易受干扰,推荐启用按节点分离的日志,从源头规避提取歧义:
- 在
http块中用map将 $upstream_addr 映射为可读 ID(如"10.0.1.10:8080" "node-a") - 定义带
$backend_id的日志格式,并在access_log路径中使用该变量:access_log /var/log/nginx/backend/$backend_id-access.log node_log; - 直接统计各独立文件请求数:
wc -l /var/log/nginx/backend/node-*-access.log,结果直观、无歧义、无需字符串切割











