轮询疑难杂症排查关键在于验证真实分发而非表面轮转:需确认未被ip_hash等覆盖、通过$upstream_addr日志统计频次、检查健康检查误剔除、排除keepalive复用及上游粘性干扰。

排查 Nginx 轮询负载均衡的“轮询疑难杂症”,关键不是看请求是否“看起来在轮”,而是验证流量是否真实、稳定、按预期分发到各节点——很多问题表面是轮询失灵,实则是连接复用、健康状态、日志盲区或配置隐性冲突导致的假象。
确认轮询是否真被启用且未被覆盖
Nginx 默认启用轮询,但极易被其他配置干扰:
- 检查 upstream 块中是否误加了 ip_hash、least_conn 或 hash $request_uri 等指令,它们会直接覆盖默认轮询逻辑;
- 确认没有在 location 或 server 块中通过 proxy_pass 指向了另一个已定义的、使用非轮询算法的 upstream;
- 若使用了第三方模块(如 sticky cookie),需单独验证其是否劫持了调度行为;
- 执行 nginx -T | grep -A 10 "upstream.*{" 查看最终生效的 upstream 配置,排除 include 或多文件覆盖导致的配置错位。
验证请求是否实际落到不同后端
不能只看配置,要从日志和连接状态反推真实分发效果:
- 在 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 复用过度导致“伪不均”;
- 检查 Nginx error_log 中是否频繁出现 "upstream connection is busy",这表明 keepalive 连接池耗尽,Nginx 被迫新建连接,使 least_conn 或轮询逻辑失效。
揪出健康检查导致的“隐形剔除”
轮询节点明明在配置里,却始终收不到请求?大概率是被动健康检查把它“静默下线”了:
- 查看 error_log 中是否有类似 "no live upstreams" 或 "upstream temporarily disabled" 的报错,定位被标记为 DOWN 的节点;
- 检查对应 server 行的 max_fails=2 fail_timeout=10s 是否过于敏感:在高延迟链路或偶发超时场景下,该配置会让节点频繁进出“不可用”状态;
- 确认后端服务的健康接口(如 /health)是否真实存在、返回 2xx、响应时间小于 proxy_connect_timeout 和 proxy_read_timeout;
- 若使用了 nginx_upstream_check_module 等主动检查模块,需单独访问 check 接口(如 /status?format=json)验证探测结果与 Nginx 实际状态是否一致。
识别客户端/协议层干扰因素
有些“不轮询”现象来自上游或传输层,和 Nginx 调度无关:
- 浏览器或客户端开启 HTTP/1.1 keepalive,且反复请求同一资源,可能被 Nginx 复用到同一个后端连接上,造成“固定打到一台”的错觉;可通过 curl 加 -H "Connection: close" 强制短连接验证;
- CDN、API 网关或前置 LB 已做了 ip_hash 或 session stickiness,导致所有请求先被固定到某台 Nginx 实例,再由它转发——此时需在 Nginx 上游入口查源 IP 分布;
- HTTPS 场景下,若启用了 TLS session reuse 或 OCSP stapling,也可能延长连接生命周期,间接影响轮询感知;
- MinIO、Elasticsearch 等特殊服务对 Host 头、路径、认证头敏感,若 Nginx 未正确透传,后端可能拒绝请求并快速返回 4xx,触发 proxy_next_upstream 重试,形成“总打第二台”的循环假象。











