能快速剔除故障节点,但默认被动健康检查下最坏需30秒;启用主动探测(如nginx_upstream_check_module)可将隔离时间压缩至3–6秒,并需调小proxy_read_timeout、规避dns缓存及浏览器重试影响。

后端宕机时,Nginx 负载均衡能否快速剔除故障节点、把流量切到健康机器,直接决定用户是否感知到“卡顿”或“502”。切换时延不是固定值,它由健康检查机制、超时参数和失败判定逻辑共同决定——关键不在“能不能切”,而在“多久能切准”。
默认轮询模式下,Nginx 实际如何感知宕机?
原生 Nginx 不主动发健康探测包,而是靠“被动失败”触发剔除:某次请求发给后端,若连接失败、响应超时或返回特定错误码(如 502/504),就记一次失败。当失败次数达到 max_fails,该节点被标记为不可用,进入 fail_timeout 的休眠期。
-
max_fails=2:连续 2 次请求失败才下线 -
fail_timeout=30s:下线后 30 秒内不再尝试,到期自动重试 - 第一次失败后,下次请求仍可能打到该节点(因未达阈值),造成“首请求失败”
要压低切换时延,必须启用主动健康检查
仅靠被动机制,最坏情况可能等满 30 秒才隔离节点。生产环境推荐加装 nginx_upstream_check_module(Tengine 衍生模块)实现主动探测:
-
check interval=2000 rise=2 fall=3 timeout=1000:每 2 秒探一次,连续 2 次成功即恢复,连续 3 次失败即下线 - 探测类型选
type=http,可配check_http_send和check_http_expect_alive验证返回状态码或内容 - 实测中,从真实宕机到完全停止转发,通常在 3–6 秒内完成
演练时必须关注的隐藏影响点
切换快≠用户体验好。以下环节会叠加延迟或引发异常:
-
客户端 TCP 连接复用:若用 keepalive,旧连接可能还卡在已宕机的后端,需等 socket 超时(默认 75 秒)才会断开,建议调小
proxy_read_timeout - 上游 DNS 缓存:若 upstream 里写的是域名,DNS 解析结果可能缓存,导致新 IP 无法及时生效
- 浏览器重试行为:部分前端 JS 在收到 502 后自动重发,可能在切换窗口期内触发重复请求
一次可落地的故障演练步骤
不用停服务,用 iptables 模拟后端瞬断更可控:
- 在目标后端服务器执行:
iptables -A INPUT -p tcp --dport 8080 -j DROP(模拟端口不可达) - 用
curl -I http://your-vip/health每秒打点,观察首次失败时间、502 出现时长、恢复时间 - 同时抓包验证:Nginx 是否在
interval内发出 HTTP 探测;后端日志是否收到探测请求 - 切回正常后,确认
fail_timeout到期前是否有误判重试











