least_conn仅统计活跃TCP连接数,不感知后端性能差异;排查重点是验证连接数是否真实反映承载压力,需结合stub_status、ss命令比对、健康检查配置及max_conns/weight等辅助机制综合分析。

least_conn 本身不感知后端性能差异,只统计活跃 TCP 连接数。当节点能力不同(如 CPU、内存、磁盘 I/O 不一致)时,连接数少未必代表负载轻——可能只是响应快、连接释放早;而连接数多的节点,也可能因处理慢、长阻塞导致连接堆积。排查重点不是算法错了,而是它看到的“连接数”是否真实反映节点实际承载压力。
确认 least_conn 是否真在按连接数选节点
先验证基础逻辑是否生效,排除配置误读或统计失真:
- 开启 stub_status 模块,压测中实时访问
/nginx_status,观察各 upstream server 的 Active connections 数值是否随请求接入动态变化,且新请求明显倾向数值更低的节点 - 在
log_format中加入$upstream_addr $upstream_connect_time $upstream_response_time,比对日志:若某台高性能节点长期连接数低但响应时间也短,说明 least_conn 正常起效;若它连接数低但响应时间反而高,需查后端是否存在隐性瓶颈(如慢 SQL、锁竞争) - 用
ss -tnp | grep :<port></port> | grep ESTAB在 Nginx 本机统计每个后端的 ESTABLISHED 连接数,与 stub_status 显示值比对。若偏差大(如 Nginx 显示 12,ss 查到 80),说明存在大量未被及时回收的僵尸连接或 keepalive 设置过长
检查性能差异是否被健康机制放大或掩盖
性能弱的节点容易因响应慢触发超时或失败,但 least_conn 不主动规避——能否绕开,取决于健康检查是否及时把它标记为不可用:
- 确保每个
server行都配了max_fails=2 fail_timeout=15s,并在 location 中启用proxy_next_upstream error timeout http_500 http_502 http_504,让慢到超时的请求也能触发失败计数 - 对关键节点部署主动健康检查(如 Nginx Plus 或带 health_check 模块的编译版),探测路径设为轻量
/health,间隔 ≤3 秒,避免等慢节点自己报错才摘除 - 观察压测中某慢节点是否出现“连接数缓慢上升→突降至 0→恢复”的周期性波动。若有,说明健康检查正在起作用;若连接数持续高位却不摘除,大概率是
proxy_next_upstream缺失timeout或fail_timeout设得过大
验证 max_conns 是否合理体现节点能力差异
当硬件性能明显不同时,仅靠连接数比较不够公平。max_conns 是最直接的容量表达方式,但它必须和实际吞吐匹配:
- 不要凭空设值。先用相同流量分别压测单台高性能节点和普通节点,记录各自稳定支撑的最大并发连接数(通过后端
ss -s或应用层连接池监控),以此为依据设置max_conns - 例如:A 节点实测可稳撑 1800 连接,B/C 节点仅 700,则配置
server A max_conns=1800;和server B max_conns=700;。这样即使 A 连接数达 1799、B 为 699,least_conn 仍会倾向 A;一旦 A 达上限,才自动切走 - 避免所有节点都设 max_conns。同构集群中它意义不大,反而增加每次调度前的判断开销;只在异构或混部场景下使用
结合 weight 与 slow_start 做辅助调节
least_conn 在连接数相等时退回到加权轮询,这是利用权重弥补性能差异的关键窗口:
- 若三台节点连接数长期接近(如都在 8–12 区间),而其中一台明显更快,可给它设
weight=2。注意:weight 不影响 least_conn 主逻辑,只在“最少连接数相同”时起作用 - 新扩容的高性能节点上线时,务必加
slow_start=30s,防止瞬间涌入大量请求压垮尚未预热的 JVM 或数据库连接池 - 禁用
ip_hash或hash $arg_xxx类策略,它们会覆盖 least_conn,导致连接数失去调度意义



















