Nginx大量TIME_WAIT/CLOSE_WAIT
Nginx出现大量 TIME_WAIT 和 CLOSE_WAIT 时,服务响应会变慢,严重时端口耗尽导致连接失败。
TIME_WAIT 是主动关闭方等待连接彻底释放的正常状态,CLOSE_WAIT 则是对端关闭后本端未主动关闭连接,属于应用层问题。
本文按零基础可操作的方式,讲清诊断方法和 TCP 内核参数完整调整步骤。
先用一条命令确认连接堆积类型
登录服务器执行下面的命令,统计当前各连接状态的数量:
ss -ant | awk '{print $1}' | sort | uniq -c | sort -n
输出中如果 TIME_WAIT 数量成百上千,说明短连接过多,属于正常但需优化;
如果 CLOSE_WAIT 数量持续增长且不下降,优先排查 Nginx 代理配置、后端接口响应,以及业务代码是否正确关闭连接。
调整 Linux TCP 内核参数,重点降低 TIME_WAIT
编辑内核参数文件:
vim /etc/sysctl.conf
在文件末尾追加以下内容:
# 加快 TIME_WAIT 回收,默认 60 秒,调小后释放更快
net.ipv4.tcp_fin_timeout = 30
# 允许复用处于 TIME_WAIT 的连接(安全场景下可用)
net.ipv4.tcp_tw_reuse = 1
# 新内核已废弃,不要设置 tcp_tw_recycle=1,会造成 NAT 丢包
# 扩大本地端口范围,避免高并发下端口耗尽
net.ipv4.ip_local_port_range = 1024 65000
# 限制 TIME_WAIT 最大数量,防止溢出
net.ipv4.tcp_max_tw_buckets = 10000
# 调整 TCP 空闲连接探测参数
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
保存后执行使其生效:
sysctl -p
执行后可以通过 sysctl net.ipv4.tcp_fin_timeout 确认参数已加载。
注意,tcp_tw_reuse 只对发起连接方有效,调低 tcp_fin_timeout 会略微缩短连接关闭等待时间,对绝大多数 Web 服务无副作用。
Nginx 配合优化,减少短连接产生
内核参数调整后,还需要修改 Nginx 配置,让连接尽量复用。
打开 Nginx 主配置文件,建议在 http 块中设置:
http {
keepalive_timeout 60;
keepalive_requests 1000;
}
如果是反向代理,还要在 upstream 块中启用连接池:
upstream backend {
server 127.0.0.1:8080;
keepalive 32;
}
配置完成后重载 Nginx:
nginx -t && nginx -s reload
开启 keepalive 后,客户端与 Nginx、Nginx 与后端连接都可以复用,从源头上减少 TIME_WAIT 的产生。
验证调优结果并避免常见坑
调优完成后观察一段时间,用 ss -s 查看整体连接概况,或者再次运行状态统计命令,看 TIME_WAIT 数量是否明显下降。
CLOSE_WAIT 数量如果仍然不降,说明不是内核参数问题,而是 Nginx 或后端应用没有正确关闭连接。
这里有几个容易踩的坑:
- 不要启用
tcp_tw_recycle:该参数在 Linux 4.12 后已移除,且开启后会导致 NAT 环境下连接被随机丢弃。 tcp_tw_reuse不要理解成回收 TIME_WAIT:它只是安全地复用已有连接,不会删除 TIME_WAIT 计数;如果追求立刻减少计数,调小tcp_fin_timeout更直接。- CLOSE_WAIT 不能靠调内核解决:需要查后端接口响应是否过慢、Nginx 代理超时配置、业务代码是否忘记关闭 Socket。
如果你正在处理 Nginx 大量 TIME_WAIT/CLOSE_WAIT 的问题,建议先按本文步骤完整执行,再根据自己的环境微调。
遇到 CLOSE_WAIT 持续增长时,优先排查应用代码,不要盲目改内核参数。
调优结束后,建议把修改过的配置文件和变更记录保存下来,方便后续审计和回滚。