轮询策略在多级代理下“看似生效、实则失效”的根本原因是请求特征被层层代理扭曲,导致nginx无法稳定识别后端状态或均匀分发,需从流量路径可信性与决策依据可靠性两方面排查。

轮询策略在多级代理环境下“看似生效、实则失效”,根本原因往往不是配置写错了,而是请求特征被层层代理扭曲,导致 Nginx 无法稳定识别后端节点状态或均匀分发。排查要从“流量路径是否可信”和“决策依据是否可靠”两个维度切入。
确认 upstream 健康检查是否真正起效
多级代理(如 CDN → WAF → Nginx LB → 后端)常导致 Nginx 的主动健康检查被拦截或失真:
- 检查 upstream 中每个 server 是否都明确配置了 max_fails=3 fail_timeout=30s;仅靠轮询本身不剔除故障节点
- 用 curl -I http://nginx-ip/healthz 直连 Nginx,观察 X-Upstream-Status 或自定义健康响应头,验证探测请求是否能穿透所有中间层到达真实后端
- 若 WAF 或 CDN 层缓存了健康检查响应(比如返回 200 却未转发到后端),Nginx 会误判节点存活——建议将健康检查路径设为唯一且不可缓存,例如加时间戳参数:/health?ts=$msec
验证客户端 IP 和会话标识是否被污染
轮询本身无状态,但多级代理可能引入隐式会话粘性,让流量持续打到同一台后端:
- 检查所有上游代理是否透传了 X-Forwarded-For,并在 Nginx 的 upstream 块中避免使用 ip_hash 或 hash $remote_addr——这两者在多级代理下会把所有用户映射成同一个 IP(如 CDN 出口 IP)
- 用 log_format debug '$http_x_forwarded_for — $remote_addr — $upstream_addr'; 记录实际转发目标,确认日志中 $upstream_addr 是否真的在多个后端间轮转,而非长期固定
- 若业务依赖 Cookie 或 Token 做路由(如某些 API 网关行为),需确认这些字段未被某一级代理篡改或重复添加
检查 proxy_next_upstream 是否掩盖了轮询逻辑
该指令会让单次请求在失败后自动重试其他节点,表面看“负载均衡了”,实则是请求级兜底,不是连接级分发:
- 查看配置中是否设置了 proxy_next_upstream error timeout http_502 http_503 且 proxy_next_upstream_tries 值较大(如 >2)——这会导致单个慢请求反复重试,掩盖轮询的原始分配节奏
- 临时注释掉 proxy_next_upstream,用 ab -n 100 -c 10 http://lb/ 压测,对比前后端日志中各节点请求数分布:若关闭后才出现明显轮转,说明原配置把轮询变成了“故障转移”
- 注意:它只影响当前请求生命周期,不会改变后续新请求的初始分配目标
确认缓存与绕过机制未干扰调度路径
当 Nginx 同时承担缓存和负载均衡角色时,缓存命中会跳过 upstream 调度,造成“轮询没跑起来”的假象:
- 添加 add_header X-Cache-Status $upstream_cache_status;,用 curl 查看响应头;若大量返回 HIT 或 STALE,说明请求根本没走到轮询逻辑
- 检查 proxy_no_cache 和 proxy_cache_bypass 是否误配——例如对带认证头的请求也允许缓存,导致不同用户命中同一缓存项,后端调用量远低于预期
- 确保 location 块中 proxy_cache 和 proxy_pass 在同一作用域,且没有嵌套 location 意外覆盖了 upstream 配置











