Nginx轮询默认不感知后端可用性,需配置被动健康检查(max_fails/fail_timeout+proxy_next_upstream)实现自动剔除;避免weight/ip_hash等干扰项;可选主动探测提升可靠性。

Nginx 轮询本身不自动感知后端是否真正可用,剔除异常节点必须靠显式配置健康检查机制。默认轮询只会按顺序发请求,哪怕某台服务已返回 502 或完全无响应,仍会持续转发,直到手动干预。要实现“自动剔除”,需组合被动检查与合理参数。
被动检查:靠真实请求失败触发隔离
这是最常用、无需额外模块的方案,依赖每次代理请求的结果来判断节点状态:
- 在 upstream 中每个 server 行加上 max_fails 和 fail_timeout,例如:
server 192.168.1.10:8080 max_fails=3 fail_timeout=30s; - 在对应 location 块中启用 proxy_next_upstream,明确哪些响应算失败,例如:
proxy_next_upstream error timeout http_500 http_502 http_503 http_504; - 当某节点在 30 秒内连续失败 3 次(连接失败、超时或返回指定 HTTP 状态),Nginx 就将其标记为 down,后续请求跳过它,直到 fail_timeout 结束后首次新请求再试探恢复。
避免常见配置失效陷阱
很多配置看似写了,实际轮询并未生效,原因常出在干扰项上:
- 删掉所有 weight= 参数——哪怕只有一行带 weight,整个 upstream 就变成加权模式,不再是纯轮询
- 整行删除 ip_hash、least_conn 等指令——注释掉也不行,Nginx 会识别并覆盖默认行为
- 不要混用 backup 或 down 标记——被标为 backup 的节点不参与常规轮询队列,down 则彻底离线
验证剔除是否真正起作用
不能只看配置文件,要通过实际操作确认效果:
- 手动停掉一台后端服务(如
systemctl stop myapp) - 快速发起多次请求(
curl -I http://nginx-ip/api/health),观察 Nginx 错误日志是否出现 upstream timed out 或 connection refused - 检查访问日志(需提前配置
$upstream_addr变量),确认后续请求不再打向已停服务的 IP:端口 - 重启该后端后,等 fail_timeout 时间过后再测,应能自然恢复流量接入
进阶建议:对关键业务加主动探测
被动检查有滞后性,适合大多数场景;但若要求更早发现“假存活”(比如进程僵死但端口还通),可引入主动健康检查:
- 使用 OpenResty 或编译 nginx_upstream_check_module
- 在 upstream 中添加:
check interval=3000 rise=2 fall=2 timeout=1000 type=http uri=/health; - 确保后端提供轻量、稳定的
/health接口,返回 200 且耗时低于 200ms


















