least_conn是Nginx基于实时活跃连接数调度的负载均衡策略,优先将请求分发给连接数最少的后端,适用于长连接多、响应时间差异大或后端性能异构的场景;它过滤不可用节点后比较活跃连接总数(含keepalive空闲连接),并支持max_conns实现软性容量控制。

least_conn 是 Nginx 原生支持的负载均衡策略,核心逻辑很简单:把新请求发给当前活跃连接数最少的后端服务器。它不看 CPU、不比响应时间,只盯住一个数字——此刻这台机器还有多少 TCP 连接没关。这对长连接多、处理时长差异大的场景特别管用。
为什么长连接下轮询容易失衡
轮询策略按顺序分发请求,假设后端有三台机器 A、B、C,其中一台在处理一个 30 秒的文件上传,另两台刚完成毫秒级查询。轮询仍会继续往那台“卡着”的机器派新请求,导致它的连接数越堆越高,而其他机器空闲。用户感知就是部分请求变慢、超时增多,监控上看到 conn_established 持续偏高,但 CPU 却不高——这正是 least_conn 要解决的典型失衡。
- 长连接(如 WebSocket、HTTP/2 流、大文件上传)会让连接长期占用,轮询无法感知这种“隐性负载”
- 后端性能异构(比如混用了不同代际的物理机或容器规格)也会放大轮询的偏差
- 接口响应时间波动大(既有 20ms 的读缓存,也有 8s 的报表导出),让静态调度策略失效
least_conn 的真实调度逻辑
Nginx 并不是简单取个最小值就完事。它在每次选节点前会做三步:
- 先过滤掉健康检查失败或被标记为 down/backup 的不可用节点
- 在剩余可用节点中,比较它们当前的活跃连接总数(包括 keepalive 空闲连接)
- 选连接数最少的那个;如果多个节点并列最少,则在这些节点里走加权轮询(注意:此时 weight 才生效)
这里的关键是:keepalive 连接会计入总数。如果你配置了 upstream 中的 keepalive 100,那每个 worker 维持的 100 条空闲连接,也会算在对应后端的连接数里。所以 keepalive 值不宜设得过大,否则可能人为拉高某台机器的“账面连接数”,干扰 least_conn 判断。
用 max_conns 实现软性容量控制
least_conn 本身不支持 weight,但你可以用 max_conns 来体现节点能力差异。比如高性能节点可承载更多并发,普通节点需限制接入量:
upstream backend {
least_conn;
server 192.168.1.10:8080 max_conns=2000; # 高配
server 192.168.1.11:8080 max_conns=800; # 普配
server 192.168.1.12:8080 max_conns=800; # 普配
}
这样,当高配节点连接数为 1999、普通节点为 799 时,新请求仍倾向高配节点;一旦它达到 2000,Nginx 就自动跳过,转投其他节点——相当于一种带容量上限的动态权重。
- max_conns 是硬限制,超过即拒绝接入,不会排队等待
- 它和健康检查独立,故障节点仍需靠 health_check 或 max_fails/fail_timeout 主动剔除
- 建议结合监控(如 nginx stub_status 或 Prometheus exporter)定期核对实际连接数与 max_conns 设置是否匹配
配置与避坑要点
基础写法很简洁,但几个细节容易踩坑:
- upstream 块内直接写 least_conn;,不需要参数,也不支持和 weight 同时出现(weight 会被忽略)
- 务必单独配置健康检查,least_conn 不自带故障熔断,例如加 check interval=3 rise=2 fall=3(需启用 ngx_http_upstream_check_module)
- 如果后端启用了 connection reuse(如 Tomcat 的 keep-alive),要确保 Nginx 的 proxy_http_version 和 proxy_set_header 适配,避免连接复用异常影响计数准确性
- 在高并发突增场景下,可配合 limit_conn 或 limit_req 做入口限流,防止 least_conn 被瞬间打满而失去调节余地











