nginx least_conn策略的核心价值是将新请求分配给当前最空闲、响应最快的后端,依据实时活跃连接数(含keepalive空闲连接),而非历史请求数或预设权重;需配合合理keepalive配置、健康检查及max_conns/weight双控以适配异构场景。

为什么活跃连接数比请求数更能反映真实负载
轮询按顺序派发,但一个耗时 10 秒的文件上传会持续占用一条连接,而同一时间其他后端可能刚处理完 5 个毫秒级查询。此时连接数差异远大于请求数差异——连接是资源占用的直接体现,请求只是瞬时事件。least_conn 抓住这个本质,避免把新请求继续压向“卡住”的节点。
尤其在以下情况,活跃连接数与实际压力高度相关:
- WebSocket 或 HTTP/2 长连接维持数十秒至数分钟,连接长期存在但无实际业务消耗
- 后端混用不同规格机器(如 CPU 核数相差 2 倍),相同连接数下处理能力差异明显
- 接口响应时间跨度大(20ms 缓存读 vs 8s 报表导出),静态调度完全失效
keepalive 连接必须计入,且配置需谨慎
upstream 中的 keepalive N 设置的不是“最大并发”,而是每个 worker 进程可为该后端缓存的空闲连接数。这些连接虽未传输数据,但仍占着端口、内存和文件描述符,least_conn 会把它们算进活跃连接总数。
若 keepalive 设得过大(比如 200),而某台后端实际业务连接仅 10 条,但空闲连接已满 200,Nginx 就会认为它“很忙”,不再分发新请求——这反而造成误判和流量倾斜。建议:
- upstream keepalive 值设为后端单实例最大并发连接数的 60%–80%(如 Tomcat maxConnections=200,keepalive 可设 120–160)
- 配合后端连接池参数(如 Tomcat 的 maxKeepAliveRequests > 0),确保空闲连接能被复用而非频繁重建
- 通过
stub_status或 Prometheus exporter 观察各后端 active connections 趋势,确认空闲连接占比合理
健康检查是 least_conn 发挥作用的前提
least_conn 只在“健康节点”中选最小值。若一台后端因 GC 卡顿、线程阻塞或网络抖动导致响应超时,但 TCP 连接未断,它仍会被视为“可用”,连接数持续上涨,least_conn 会不断把新请求导向它——结果就是越分越堵。
必须配合主动或被动健康检查机制:
- 启用
proxy_next_upstream error timeout http_500 http_502,配合max_fails=2 fail_timeout=15s让异常节点及时摘除 - 有条件时使用 active health check(商业版或开源 patch),每 3–5 秒探测 HTTP 状态码与关键响应头
- 避免仅依赖默认失败重试,那无法识别“活着但卡住”的状态
用 max_conns 或 weight 补偿节点能力差异
least_conn 本身不支持 weight 参数影响初始选择逻辑,但它支持 max_conns 作为软性容量控制:当某节点连接数达到 max_conns 时,即使它仍是“最少”,Nginx 也会跳过它,转而选择次优节点。
这对异构集群非常实用:
- 高性能节点设
max_conns=2000,普通节点设max_conns=800,天然适配硬件差异 - weight 参数仍在 least_conn 的“并列最小”场景生效:当多个节点连接数同为最低时,Nginx 在它们之间走加权轮询
- weight + max_conns 双控,比单靠 weight 更贴近真实吞吐瓶颈(比如 CPU 饱和前连接数已逼近上限)











