least_conn算法基于Nginx与后端间活跃TCP连接数调度,适用于AI推理等长耗时接口;须置于upstream首行,禁用weight改用max_conns,需配置keepalive、健康检查及超时参数确保连接真实反映负载。

least_conn 算法本身不看耗时、不算力,只认一个数:Nginx 与后端之间当前已建立、尚未关闭的活跃 TCP 连接数。对耗时长、算力重的接口(如 AI 推理、大模型打分、复杂报表生成),连接往往长期占用,轮询会持续往“卡着”的节点派新请求,而 least_conn 能自动绕开它——只要连接没释放,数字就高,新请求自然流向更空闲的节点。
必须写对的位置和基础结构
least_conn 只能在 upstream 块首行声明,不能放在 http、server 或 location 里:
- 正确写法:upstream ai_backend { least_conn; server 10.0.1.5:8000; server 10.0.1.6:8000; }
- weight 参数会被静默忽略,不要写 server ... weight=2;想体现节点能力差异,改用 max_conns=1500(高性能节点)或 max_conns=600(普通节点)
- 同一 upstream 中禁止混用 ip_hash、hash、least_time 等互斥策略
让连接数真实反映“手头活儿”多少
如果后端每处理一个请求就新建再断开连接,活跃连接数始终趋近于 0,least_conn 就退化成随机分配。必须让连接真正“活”起来:
- 在 upstream 块中加:keepalive 32;(每个 worker 缓存最多 32 条空闲长连接)
- 在 proxy_pass 所在的 location 中加:proxy_http_version 1.1; proxy_set_header Connection '';
- 后端服务要支持长连接:比如 FastAPI 需启用 Uvicorn 的 keep-alive timeout,PyTorch Serving 默认支持 HTTP/1.1 复用
- 对纯计算型接口(无文件流、无 SSE),可将 keepalive_timeout 5s(全局或 location 级),避免空闲连接长期占位干扰统计
防“假空闲”和单点拖垮
算力重的接口容易出现长尾请求(如某次推理卡在 GPU 内存不足),导致该节点连接数低但实际不可用,或连接数被撑满却还在收新请求:
- 必须配健康检查:用 max_fails=2 fail_timeout=10s 快速摘除异常节点;若用 OpenResty,推荐 check interval=2 rise=1 fall=2 timeout=3 type=http
- 为每个 server 设置 max_conns=800(举例),一旦达到即剔出调度池,防止慢请求锁死整条连接队列
- 在 location 中加 proxy_read_timeout 120;(略高于后端 P99 处理时间),避免超长等待阻塞连接复用
验证是否真正在按压力调度
别只看配置有没有报错,重点看行为是否符合预期:
- 开启 stub_status,在 server 块中加:location /nginx_status { stub_status; },访问后观察各 server 的 active 连接数是否随压测动态变化、大致均衡
- 在后端机器上执行:ss -o state established '( dport = :8000 )' | wc -l,比对 Nginx 统计值是否一致
- 压测时用 wrk -t4 -c200 -d30s http://lb/api/infer,再查各后端 access log 的请求数分布——应随连接数波动而动态偏移,而非固定比例

















