least_conn节点下线后连接不迁移,本质是nginx仅按连接数调度且未及时感知节点异常;需排查健康检查配置、连接数统计真实性及新请求是否真正绕过该节点。

least_conn 节点下线后连接不迁移,本质是 Nginx 没有及时感知节点异常或未正确跳过它——它只看“连接数”,不自动判断“是否还能用”。排查要聚焦三点:节点是否真被剔除、连接数统计是否真实、新请求是否真的绕开了它。
确认节点是否已被健康检查标记为不可用
least_conn 本身不剔除节点,全靠健康检查机制。如果节点已卡死但 TCP 连接未断,被动检查(靠失败响应触发)可能迟迟不生效。
- 检查 upstream 中每个 server 是否配置了 max_fails=2 fail_timeout=15s,这是被动检查的基础
- 验证 proxy_next_upstream 是否包含 error timeout http_500 http_502,否则超时或错误不会触发重试和剔除
- 用 curl -I http://your-nginx-ip/nginx_status 查看 stub_status 输出,确认对应 server 的 Down 状态是否为 1;若一直是 0,说明健康检查没起作用
- 临时在后端加一个轻量健康探针(如
/health),并用 tcpdump 或后端日志确认 Nginx 是否真在定期访问它
验证连接数统计是否反映真实负载
如果后端用短连接(每请求新建+关闭),Nginx 统计的活跃连接数瞬间归零,least_conn 就失去意义,新请求仍可能打到已下线但“账面空闲”的节点。
- 在 upstream 块中确认是否设置了 keepalive 32(推荐值 16–64)
- 在 location 块中确认是否启用 HTTP/1.1 长连接:proxy_http_version 1.1 和 proxy_set_header Connection ''
- 登录后端机器,执行 ss -tan | grep :8080 | grep ESTAB | wc -l,对比该数值与 stub_status 中的 Active connections 是否接近;偏差大说明连接复用失效或存在泄漏
- 检查后端响应头是否含 Connection: close(常见于错误返回、调试开关或 WAF 干预),这会强制断连,让 keepalive 失效
观察新请求是否实际跳过下线节点
即使节点被标记为 Down,若配置有 backup 或 down 标记,或 max_conns 未设限,Nginx 可能仍尝试转发或 fallback 到其他逻辑。
- 在 log_format 中加入 $upstream_addr $upstream_connect_time $upstream_state,压测时抓取日志,看失败请求是否还落到该 IP:Port
- 若看到 upstream_state 显示 “502 504” 或 “timeout”,且地址仍是下线节点,说明 proxy_next_upstream 未生效或重试次数不足
- 检查是否有 ip_hash、hash $request_uri 等哈希类指令混用——它们会覆盖 least_conn,导致请求始终固定打向某台
- 确认没有遗漏 slow_start=30s 等参数干扰:新上线节点若配了 slow_start,而旧节点刚下线,流量可能短暂集中到剩余节点中某一台
快速验证与补救建议
上线前可做三步快速验证:先手动把一台后端进程 kill,再发 10 个并发请求,最后查日志和连接分布。
- 若请求仍落到宕机节点,优先补上 proxy_next_upstream timeout error http_502 和 max_fails/fail_timeout
- 若连接数统计长期为 0,重点检查后端是否关闭了 Keep-Alive,或 Nginx 是否漏配 proxy_http_version 1.1
- 若想立即隔离节点,可在 upstream 中临时加上 down 标记,比等健康检查更直接











