least_conn算法失效导致某后端连接数持续偏高,需分层排查:nginx是否真在选它(查access_log和error_log)、后端是否真在处理(查连接状态、应用池、jvm)、健康检查是否滞后(建议启用active check)、keepalive与max_conns配置是否干扰统计。

当 Nginx 使用 least_conn 算法,却出现某个后端节点连接数持续偏高,说明该算法未能真实反映其负载,或该节点已陷入“假空闲”状态——表面连接数不高,实则响应迟缓、连接堆积、资源卡死。排查不能只看 Nginx 的“连接数”,而要分层验证:Nginx 是否真在选它、后端是否真在处理、连接是否被有效复用或及时释放。
确认 Nginx 是否仍在将请求导给该节点
先排除配置误判或统计延迟:
- 检查 access_log 中
$upstream_addr字段,用命令(如awk '{print $NF}' access.log | sort | uniq -c | sort -nr)统计各节点被选中的频次——若某节点占比远超其他(例如 >2.5 倍),说明 least_conn 实际在持续选择它 - 查看 error_log(debug 级别)中是否有
"no live upstreams"或"upstream connection is busy",前者表示其他节点因max_conns或健康检查失败被剔除,后者说明 keepalive 连接池耗尽,被迫新建连接,导致 least_conn 失效 - 确认 upstream 配置未混用
ip_hash或hash $request_uri等绑定类指令,它们会覆盖 least_conn 的动态选择逻辑
查清该节点实际连接状态与资源占用
连接数居高不下,可能是真忙,也可能是“僵死”:
- 在该节点上执行
ss -tn state established | grep :8080 | wc -l(替换为实际端口),对比其他节点数值;若显著偏高,再查netstat -s | grep "connection resets"看是否存在大量异常断连 - 检查应用层连接池指标:如 Java 应用的 HikariCP
ActiveConnections、Druid 的ActiveCount,确认是否已达maxPoolSize并长期不降 - 观察 JVM GC 日志或系统
top -H -p [pid],确认是否存在线程阻塞、Full GC 频繁或 I/O 等待,这类问题会让连接“挂着不释放”,但 least_conn 仍视其为“可承接新请求”
验证健康检查是否失效或滞后
least_conn 不自带故障感知,依赖健康检查来剔除异常节点。若检查太弱,就会把“卡住但没挂”的节点继续纳入调度:
- 检查是否仅用 passive 模式(靠
proxy_next_upstream触发),这种模式需等请求失败才反应,无法发现“连接建立成功但响应超时”的情况 - 建议启用 active health check(如 nginx_upstream_check_module),配置
interval=3s fails=2 passes=2,并确保检查路径轻量、绕过鉴权和缓存(如单独暴露/health) - 若只能用 passive 模式,请收紧
max_fails=2 fail_timeout=10s,并开启proxy_next_upstream error timeout http_500 http_502,让慢节点更快被隔离
检查 keepalive 与 max_conns 配置是否干扰判断
不当的连接复用设置会让 least_conn 的“连接数”失去参考价值:
- 确认 upstream 中
keepalive值是否合理:过大(如 200)会导致空闲连接长期占位,拉高账面连接数;过小(如 4)则频繁建连,使 least_conn 统计失真。建议按后端单实例并发能力反推,常见值为 16–32 - 检查该节点是否设置了
max_conns。若未设,而其他节点设了且已达上限,Nginx 会自动跳过它们,所有流量涌向该节点——此时不是它“被选中”,而是其他节点“被排除” - 确认后端是否返回
Connection: close(尤其在错误响应或 WAF 干预时),这会强制关闭 keepalive 连接,导致 Nginx 反复新建连接,放大该节点压力











