CLOSE_WAIT大量堆积本质是服务端未主动关闭socket,属程序逻辑或资源管理问题;需同步排查连接归属、进程状态及代码中accept/close配对、异常分支释放、连接池超时等环节。

CLOSE_WAIT 大量堆积,本质是服务端没主动关连接,不是内核问题,而是程序逻辑或资源管理出了问题。排查必须从连接归属、进程状态、代码行为三方面同步推进。
快速统计和定位异常连接
先确认问题规模和分布:
- 查总数:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' | grep CLOSE_WAIT - 查具体连接(含PID):
ss -tanp | grep CLOSE-WAIT(需 root;若无权限,用lsof -iTCP -sTCP:CLOSE_WAIT -n -P) - 看哪个端口最严重:
ss -tanp | grep CLOSE-WAIT | awk '{print $5}' | cut -d':' -f2 | sort | uniq -c | sort -nr
检查对应进程是否异常
拿到 PID 后,重点验证进程是否“活着但卡住”:
Linux 安全审计工具,检查 SSH 配置、开放/监听端口、防火墙规则(ufw/iptables/nftables)、失败登录尝试、sudoers 权限...
- 查基本状态:
ps -p <pid> -o pid,ppid,comm,etime,stat,cmd</pid>,关注stat是否为S(睡眠)或Z(僵死),etime是否过大(运行时间超长可能意味阻塞) - 查文件描述符占用:
ls -l /proc/<pid>/fd/ | wc -l</pid>,对比 ulimit 限制(ulimit -n),判断是否接近上限 - 查堆栈(如 Java 进程):
jstack <pid></pid>看线程是否卡在 I/O、锁或未关闭的流上
聚焦代码与连接生命周期
CLOSE_WAIT 持续存在,90% 源于 socket 关闭缺失。检查以下环节:
- 所有
accept()返回的 socket,是否每个分支(包括异常 catch 块)都调用了close()或等效释放操作 - 使用 HttpClient、OkHttp 等客户端时,是否显式调用
close()或使用 try-with-resources;避免只关 response 而漏关 connection - 连接池配置是否合理:空闲连接是否设置了
maxIdleTime或idleTimeout;是否启用了evictIdleConnections - 多线程/多进程场景下,socket 是否被意外继承或重复引用(如 fork 后父进程未关闭监听 socket)
临时缓解与长期加固
线上紧急情况下可双管齐下:
- 临时调高资源上限(治标):
echo "* soft nofile 65536" >> /etc/security/limits.conf,并确保 PAM 加载生效 - 强制清理僵死连接(慎用):
tcpkill -9 host <ip> and port <port></port></ip>,仅适用于确认对端已不可达的连接 - 长期建议:在关键 socket 操作处加超时控制(如
setSoTimeout())、引入连接泄漏检测(如 Netty 的 ResourceLeakDetector)、日志中记录连接建立/关闭 traceId

















