least_conn在http/2下未失效但统计错位:它统计tcp连接数,而单个http/2连接可承载数百流,导致低估真实并发压力;需验证是否复用干扰、配置合理及健康检查有效。

least_conn 在 HTTP/2 多路复用下不会直接“失效”,但它的统计逻辑与 HTTP/2 的连接模型存在天然错位——它统计的是 TCP 连接数,而一个 HTTP/2 连接可承载数百个并发流(streams),导致连接数严重低估真实并发压力。排查重点不是算法出错,而是确认它是否在统计“对的对象”。
确认 least_conn 是否被 HTTP/2 连接复用干扰
HTTP/2 客户端复用单个 TCP 连接发送大量请求,Nginx 的 upstream 连接池可能只维持极少数长连接,造成 least_conn 始终在“1 vs 1 vs 1”之间轮选,失去区分度。
- 在 access_log 中添加
$upstream_addr $connection_requests $upstream_connect_time,压测时观察:若同一客户端 IP 长时间只打到同一个 upstream 地址,且$connection_requests持续上升(如从 1 到 200+),说明复用已发生,least_conn 实际只看到“1 条连接” - 用
h2load -n 1000 -c 1 -H "Connection: keep-alive"单连接压测,对比ab -n 1000 -c 10多连接压测下的 upstream 分布差异——前者连接数趋同,后者才体现 least_conn 差异
检查 upstream 连接复用配置是否掩盖真实负载
keepalive 设置过高、proxy_http_version 未显式设为 1.1、或后端未正确响应 Connection 头,都会让 Nginx 错误维持大量空闲连接,使 least_conn 统计失真。
- 确保 upstream 块中启用
keepalive 32;(不建议超过 64),并搭配proxy_http_version 1.1;和proxy_set_header Connection ''; - 检查后端是否返回
Connection: keep-alive响应头;若后端强制关闭连接(如 Spring Boot 默认关闭 keepalive),Nginx 就无法复用,least_conn 退化为近似轮询 - 用
ss -tn state established | grep :<backend_port></backend_port>在 Nginx 本机直查 ESTABLISHED 连接数,比对日志中$upstream_addr分布——若某节点 ss 显示 50 条连接,但日志里只出现 5 次,说明连接未被有效复用或统计延迟
验证 least_conn 是否因健康状态误判而失效
HTTP/2 下连接复用率高,但后端若出现高延迟(如 DB 锁、GC 暂停),TCP 连接仍存活,least_conn 会继续将新流导向该节点,加剧拥塞。此时问题不在连接数统计,而在“可用性”未被识别。
- 必须启用主动健康检查:
health_check interval=3 fails=2 passes=2 match=http_2xx;,避免仅靠被动错误(error/timeout)触发摘除 - 在 location 中开启重试:
proxy_next_upstream error timeout http_504;+proxy_next_upstream_timeout 8s;,让超时请求及时转向其他节点 - 观察
$upstream_response_time日志字段:若某节点平均值显著高于其他(如 2s vs 0.05s),但连接数却更低,说明 least_conn 正在“信任一个慢节点”,需结合健康检查收紧策略
区分 HTTP/2 流量和普通 HTTP 流量的调度路径
HTTP/2 请求走的是 HTTP 层 upstream,但若你同时用 stream 模块代理 TLS 或 gRPC over HTTP/2,least_conn 不生效——stream 模块不支持 least_conn,只支持轮询和 hash。
- 确认你的 HTTP/2 服务是否由
http { upstream {} }定义;若走stream { upstream {} },则 least_conn 完全不参与调度 - 检查 server 块是否启用
http2 on;,并确保 SSL 配置完整(ALPN 必须协商成功),否则降级为 HTTP/1.1,least_conn 行为不可比 - 在 error_log 中搜索
"upstream connection is busy":该提示表示当前 worker 的 keepalive 连接池已空,Nginx 被迫新建连接,此时 least_conn 决策被绕过,需调低keepalive值或增加 worker_connections











