轮询分发不均匀的根源在于真实流量未按预期落到各后端,需排查隐性配置覆盖、日志与连接数异常、健康检查误剔及keepalive干扰。

轮询分发不均匀,问题往往不在“轮询算法本身”,而在于真实流量是否按预期落到各后端——表面看请求在转,实际可能被复用、误剔、覆盖或日志误导。
确认轮询没被其他策略悄悄覆盖
默认轮询极易被隐性配置干扰:
- 检查 upstream 块里有没有 ip_hash、least_conn 或 hash $request_uri 这类指令,它们会直接禁用轮询;
- 确认 proxy_pass 指向的 upstream 名称没有在别处重复定义且用了不同算法;
- 执行 nginx -T | grep -A 10 "upstream.*{" 查看最终生效的配置,排除多文件 include 导致的覆盖;
- 若用了 sticky cookie 或第三方模块,需单独验证其是否劫持了调度逻辑。
用日志和连接数验证真实分发效果
不能只信配置,要从数据反推:
- 在 access_log 中加入 $upstream_addr 和 $upstream_response_time,采集 100+ 请求,统计各后端 IP 出现频次——长期偏离 1/N(N 为节点数)就说明异常;
- 注意 $upstream_addr 显示类似 "192.168.1.10:8080, 192.168.1.11:8080" 表示发生重试,需结合 proxy_next_upstream 判断是否因失败跳转;
- 在每台后端运行 ss -tn state established | grep :8080 | wc -l,对比 ESTABLISHED 连接数——某节点持续偏高,可能是 keepalive 复用过度或连接未释放;
- 查 error_log 是否频繁出现 "upstream connection is busy",这是 keepalive 连接池耗尽的信号,会导致新建连接,破坏轮询节奏。
排查健康检查导致的“隐形下线”
节点明明在配置里,却收不到请求?大概率被被动健康检查静默剔除了:
- 搜索 error_log 中的 "upstream temporarily disabled" 或 "no live upstreams",定位被标记为 DOWN 的节点;
- 检查对应 server 行的 max_fails=2 fail_timeout=10s 是否太敏感——高延迟或偶发超时会让节点频繁进出不可用状态;
- 确认后端 /health 接口存在、返回 2xx、响应时间小于 proxy_connect_timeout 和 proxy_read_timeout;
- 若只是临时波动,可调大 fail_timeout(如设为 30s)并增加 max_fails(如设为 3),避免震荡。
检查 keepalive 和客户端行为干扰
长连接会掩盖轮询效果,让“看起来没轮匀”:
- upstream 块中配置 keepalive 32;,并在 location 中添加 proxy_http_version 1.1; 和 proxy_set_header Connection '';,防止短连接反复建连放大偏差;
- 如果客户端大量使用长连接(如 App、gRPC),而部分后端主动关闭连接(Connection: close 或 timeout 过短),这些后端连接数始终偏低,Nginx 就会持续往它们身上打新请求;
- 可在 Nginx 本机用 ss -tn dst :8080 | awk '{print $5}' | cut -d: -f1 | sort | uniq -c 统计发往各后端的活跃连接,与日志频次交叉比对。











