least_conn算法通过协同机制让调度真实反映后端负载:只统计活跃TCP连接(含keepalive空闲连接),先过滤健康异常节点,连接数相同时才按weight加权轮询,并依赖upstream zone实现多worker共享连接计数。

最少连接算法在分布式架构下不是简单比数字,而是靠一套协同机制让调度真正反映后端真实负载。
它只看“活着的连接”,但这个“活”有明确定义
least_conn 统计的是当前所有 活跃 TCP 连接数,包括:
- 正在处理请求的连接(比如一个 5 秒的报表导出)
- HTTP/1.1 keepalive 空闲连接(只要没超时、没被主动关闭,就算)
- HTTP/2 或 WebSocket 的长连接(哪怕只是心跳维持)
它 不看 CPU、内存、响应时间或队列长度,只认连接是否建立且未关闭。所以当后端大量维持 keepalive 连接时,这个数字就非常关键——配置 upstream keepalive 100,每个 worker 就可能为同一台后端多算出近百条“账面连接”,影响调度公平性。
健康状态决定谁能参与比较
算法执行前必须完成过滤,否则“最少”毫无意义:
- 主动健康检查失败(如 commercial 版的 health_check 指令)的节点直接剔除
- 被动检查触发的节点:通过 proxy_next_upstream error timeout http_500 配合 server 的 max_fails=2 fail_timeout=15s,连续失败 2 次后 15 秒内不再参与调度
- 显式标记为 down 或 backup 的节点不计入候选池
没有这套机制,一台已卡死但 TCP 连接尚未断开的后端,会持续显示“连接数少”,反而成为新请求的黑洞。
多个节点并列最少时,才启用权重逻辑
least_conn 本身不按 weight 分发,weight 只在“连接数相同”时起作用:
- 假设 A、B、C 当前连接数都是 7,而配置了 weight=3、2、1,则下一次请求按加权轮询规则选 A
- 如果 A 是 7、B 是 8、C 是 9,那不管 weight 多高,一定选 A
这意味着 weight 在 least_conn 中是“次级调节器”,不是主调度依据。若需体现硬件差异,更推荐用 max_conns 做硬性容量控制,例如高性能节点设 max_conns=2000,普通节点设 800。
所有 worker 进程必须共享连接计数
Nginx 默认每个 worker 独立维护连接数统计。若启用了多个 worker(常见于多核服务器),却没配 upstream zone,就会出现:
- Worker-1 认为后端 A 连接最少,把请求全打过去
- Worker-2 完全不知道,也把请求打向 A
- 结果 A 实际连接远超预期,而 B、C 空闲
解决方法是在 upstream 外层声明共享内存 zone:
upstream backend {zone backend_zone 64k;
least_conn;
server 10.0.1.10:8080;
server 10.0.1.11:8080;
}
这样所有 worker 才能基于同一份实时连接数据做决策。


















