连接池耗尽的本质是新连接无法进入队列,需同步调优内核队列(tcp_max_syn_backlog、somaxconn)、本地端口范围(ip_local_port_range)、time_wait复用(tcp_tw_reuse),并启用upstream keepalive、proxy_http_version 1.1与connection头清理,配合健康检查和主动探测。

连接池耗尽导致的超长排队超时,本质不是“等太久”,而是新连接根本进不了队列——Nginx 想发请求,但没可用连接可用,只能排队或直接失败。解决重点不在拉长 timeout,而在疏通连接通路、扩大承载能力、及时识别瓶颈。
看清连接池耗尽的真实表现
别只盯着日志里的 “upstream timed out” 或 “Connection refused”。真正线索藏在底层状态里:
-
SYN_SENT 大量堆积:用
ss -ant | grep :端口 | grep SYN_SENT查,说明 Nginx 发了 SYN,但后端没回 SYN-ACK——可能是后端 accept 队列满、防火墙拦截、或路由不通 -
accept 队列溢出:执行
ss -lnt | grep 后端端口,若 Recv-Q 持续 ≥ Send-Q(比如显示129 128),说明已完成三次握手的连接卡在队列里,新连接被丢弃 -
TIME_WAIT 过多且复用不足:
ss -s | grep -i time_wait显示数万,而net.ipv4.tcp_tw_reuse未启用,本地端口快速耗尽,无法新建连接
针对性扩容与调优连接承载能力
连接池不是抽象概念,它由内核队列、本地端口、Nginx worker 连接数三者共同决定:
-
增大内核连接队列:
net.ipv4.tcp_max_syn_backlog = 65535net.core.somaxconn = 65535
修改后需重启或sysctl -p生效;Nginx stream 或 http 的 upstream server 行要加backlog=65535 -
放开本地端口范围:
net.ipv4.ip_local_port_range = "1024 65535"—— 提供约 64K 可用临时端口 -
允许 TIME_WAIT 复用:
net.ipv4.tcp_tw_reuse = 1(需确保客户端支持 timestamp,现代 Linux/Windows 默认开启)
让连接池“活”起来:复用 + 健康检查 + 主动释放
光扩大容量不够,还得让连接流转起来:
-
启用 keepalive 连接复用:
在 upstream 块中配置:keepalive 32;
在 location 中对应加:proxy_http_version 1.1;<br>proxy_set_header Connection '';
-
配合理想的健康检查:
HTTP 场景用health_check interval=5 fails=2 passes=1(Nginx Plus)或开源模块;
TCP 场景必须用nginx_upstream_check_module的 tcp_check;
检查间隔建议设为proxy_connect_timeout × 2,避免误判 -
主动关闭空闲连接:
keepalive_timeout 60s;控制客户端长连接;proxy_socket_keepalive on;(1.15.3+)让 Nginx 主动探测后端连接是否存活,及时断开失效连接
验证是否真解决,而不是“看起来好了”
改完配置不能只 reload 就完事:
- 压测时实时观察:
ss -s看 total connected、time-wait 数量变化趋势 - 模拟故障:临时
iptables -A OUTPUT -d 后端IP -j DROP,看健康检查是否 10 秒内摘除节点,恢复后是否自动加回 - 抓包确认:用
tcpdump -i any port 后端端口查是否有大量重传、RST 或无响应的 SYN











