根本原因在于nginx默认使用短连接导致time_wait堆积;需在upstream中配置keepalive并配合location中设置proxy_http_version 1.1和proxy_set_header connection ""来启用长连接,辅以内核参数优化。

根本原因在于Nginx默认与后端服务使用短连接,每次请求结束后主动断开TCP连接,而主动关闭方会进入TIME_WAIT状态并持续2MSL(通常60秒)。当QPS升高时,短连接频繁创建和销毁,就会在Nginx或后端服务器上堆积大量TIME_WAIT连接——尤其当后端是Java、PHP-FPM等默认不保持长连接的服务时,问题更明显。
确认是否由短连接引发
先验证问题根源,避免误调:
- 用
netstat -an | grep TIME_WAIT | awk '{print $5}' | sort | uniq -c | sort -rn | head -10查看TIME_WAIT主要连向哪个后端IP:PORT;若集中指向某台上游服务器(如192.168.1.10:8080),说明是Nginx→后端的连接在暴增 - 检查Nginx配置中对应
upstream块是否缺失keepalive指令,且location中未启用HTTP/1.1 keepalive头 - 抓包验证:用
tcpdump -i any port 8080 -nn -c 20观察四次挥手是否由Nginx(服务端口)主动发起FIN——若是,即Nginx正在主动断连
开启Nginx到后端的长连接
这是最直接有效的解法,分两步配置,缺一不可:
-
在upstream块中启用连接池:
upstream backend {<br> server 192.168.1.10:8080;<br> keepalive 200;<br>}
其中200表示每个worker进程最多缓存200个空闲长连接;值不宜过大(超过500可能挤占短连接资源),也不宜过小(低于32效果有限) -
在location中透传Keep-Alive协议头:
location / {<br> proxy_pass http://backend;<br> proxy_http_version 1.1;<br> proxy_set_header Connection "";<br>}proxy_http_version 1.1让Nginx用HTTP/1.1发请求;Connection ""清空客户端可能带的Connection: close头,避免干扰后端判断
配合调整内核参数(辅助手段)
仅靠长连接就能大幅降低TIME_WAIT,但若仍有残余压力,可安全加固系统层:
- 启用端口复用:
net.ipv4.tcp_tw_reuse = 1(允许将TIME_WAIT套接字快速重用于新连接,NAT环境下安全) - 禁用危险回收:
net.ipv4.tcp_tw_recycle = 0(该参数在有NAT或多路径场景下会导致连接异常,必须关闭) - 适度缩短FIN超时:
net.ipv4.tcp_fin_timeout = 30(加快非TIME_WAIT状态的关闭流程,不影响TIME_WAIT本身时长) - 增大TIME_WAIT桶上限:
net.ipv4.tcp_max_tw_buckets = 32768(防被填满触发内核强制回收)
写入/etc/sysctl.conf后执行sysctl -p生效。
验证与观察
配置生效后,重点看三项变化:
- 用
ss -s | grep "timewait"对比前后数量,理想情况应下降70%以上 - 运行
watch -n 1 'ss -o state time-wait | wc -l'实时观察波动趋势 - 检查Nginx error日志是否还有
connect() failed (111: Connection refused)——该错误常因端口耗尽引发,减少即说明有效
不复杂但容易忽略的是:后端服务自身也需支持HTTP/1.1 Keep-Alive(如Tomcat默认开启,Spring Boot内嵌Tomcat无需额外配置),否则Nginx发来的keepalive请求会被后端无视并仍主动断连。











