中转平台遇到大量CLOSE_WAIT连接,内核参数调优
中转平台上一旦出现大量 CLOSE_WAIT 连接,通常意味着对端已经关闭连接,而本机程序未能及时调用 close() 释放资源。
连接长期堆积会占满文件描述符,导致新请求无法建立。
本文针对中转平台这类高并发代理服务,给出可执行的内核参数调整步骤,并说明哪些参数能改、哪些参数不建议动。
先确认 CLOSE_WAIT 的数量和来源
登录服务器后,先用下面命令查看当前 TCP 连接状态分布:
ss -ant | awk '{print $1}' | sort | uniq -c | sort -rn
如果 CLOSE_WAIT 数量上千且持续增长,再执行 ss -ant | grep CLOSE_WAIT | tail -n 20 查看对端 IP。
这些 IP 通常是上游 API 服务或客户端,如果集中来自某一台服务器,可能需要检查对应程序是否有连接泄漏。
临时调整内核参数,快速缓解压力
以下参数可以先用 sysctl -w 临时生效,测试没问题后再写入配置文件。
注意,tcp_fin_timeout 主要影响 FIN_WAIT,对 CLOSE_WAIT 的回收作用有限,真正起作用的是 keepalive 探测和超时机制:
sysctl -w net.ipv4.tcp_fin_timeout=30
sysctl -w net.ipv4.tcp_keepalive_time=600
sysctl -w net.ipv4.tcp_keepalive_intvl=30
sysctl -w net.ipv4.tcp_keepalive_probes=3
sysctl -w net.ipv4.tcp_max_tw_buckets=5000
tcp_keepalive_time 表示空闲多久开始探测,tcp_keepalive_intvl 是每次探测间隔,tcp_keepalive_probes 是连续失败多少次后断开连接。
这套组合可以让长期不读写的僵尸连接更快被系统回收,间接减少 CLOSE_WAIT 堆积。
持久化配置,重启不丢
确认临时参数生效后,编辑 /etc/sysctl.conf 写入以下内容:
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.ip_local_port_range = 1024 65535
然后执行 sysctl -p 让配置生效。
如果你的中转平台需要大量新建连接,建议同时调大文件描述符限制,在 /etc/security/limits.conf 中增加:
* soft nofile 65535
* hard nofile 65535
避坑:这些参数不要乱调
不要开启 tcp_tw_recycle。
这个参数在 NAT 环境下会导致随机丢包,而且 Linux 5.12 之后内核已移除该选项。tcp_tw_reuse 只对客户端出站连接有效,无法清理服务端 CLOSE_WAIT。
另外,
把 tcp_fin_timeout 调得过小(比如低于 15)可能造成正常连接被提前断开,
建议保持 30 秒左右。tcp_max_tw_buckets 调小虽然能控制 TIME_WAIT 数量,
但会导致某些连接异常,
非必要不建议低于 5000。
内核参数只是辅助,CLOSE_WAIT 的根本原因是应用层没有正确关闭连接。
检查中转平台代码,确认对上游响应是否读完并调用 close();
如果使用 HTTP 连接池,确认空闲超时配置是否合理。
验证效果:看连接数是否回落
调整后等待几分钟,再次执行:
ss -ant | grep CLOSE_WAIT | wc -l
更直观的方式是 watch 动态监控:
watch 'ss -ant | grep CLOSE_WAIT | wc -l'
同时观察业务日志里是否出现“Connection reset”“Too many open files”等报错。
如果 CLOSE_WAIT 数量稳定下降,说明参数调优生效;
如果仍持续上涨,请优先排查应用层连接管理逻辑,而不是继续堆内核参数。
如果你正在处理中转平台大量 CLOSE_WAIT 连接,建议先按本文步骤完整执行,再根据自己的环境做微调;
遇到异常时优先回看避坑和高频问题部分。