CLOSE_WAIT过多是程序未调用close()导致的资源泄漏,会持续占用文件描述符、端口和内存,引发“Too many open files”或连接失败;需用netstat或ss统计状态、ss -tanp或lsof定位泄漏进程,并检查应用层socket关闭逻辑。

CLOSE_WAIT 过多不是网络配置问题,而是程序没关 socket 的明确信号。它不自动消失,会持续占用文件描述符、端口和内存,最终导致 Too many open files 或新连接失败。
确认 CLOSE_WAIT 数量是否异常
先看总量是否超出日常基线:
- ss -s | grep close —— 快速统计当前各状态连接数
- netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}' —— 按状态分组计数
- 如果 CLOSE_WAIT 占比高(比如 > ESTABLISHED 的 20%)或持续增长,需立即介入
定位是哪个进程在泄漏连接
查出具体 PID 和服务名,才能对症下药:
- ss -tanp | grep CLOSE_WAIT —— 显示所有 CLOSE_WAIT 连接及对应进程(需 root 权限)
- 若权限受限,可用 lsof -iTCP -sTCP:CLOSE_WAIT -n -P 替代
- 重点关注:同一进程反复出现大量 CLOSE_WAIT、且本地端口分散、远端地址多样——基本可判定是该进程未正确释放连接
检查应用层是否遗漏 close() 调用
CLOSE_WAIT 出现在被动关闭方,说明对端已发 FIN,本机内核已回 ACK,但你的代码还没调 close() 或等效方法:
- Java:检查 HttpClient、OkHttp、数据库连接池(如 HikariCP)是否配置了
connection-timeout和socket-timeout;确认 finally 块或 try-with-resources 中是否真正释放了 InputStream / Socket / Connection - Python:requests 默认复用连接,但若手动创建 urllib3.PoolManager 或 socket,必须显式调用
close();检查是否有未关闭的response对象 - Go:
http.Client通常自动管理,但自定义RoundTripper或直接使用net.Conn时,务必 defer conn.Close() - 通用线索:日志中频繁出现 read timeout、connection reset、或空 response 后无 close 日志,往往是泄漏前兆
验证修复效果与临时缓解
改完代码上线后,不能只看数量降没降,还要观察行为是否健康:
- 用 watch -n 2 'ss -s | grep close' 持续观察 CLOSE_WAIT 是否稳定回落
- 配合 lsof -p $PID | wc -l 查看该进程打开文件数是否同步下降
- 临时应急(仅限紧急止血):kill -9 $PID 重启服务,但必须同步推进代码修复,否则问题必然重现


















