首页/网络/抓包与流量分析速查/TCP CLOSE_WAIT 堆积排查
TCP 流分析82 条

TCP CLOSE_WAIT 堆积排查

CLOSE_WAIT 表示对端已发 FIN、本端应用尚未 close:大量堆积即应用侧未正确关闭连接(典型代码 bug 或线程阻塞)。

被动关闭堆积在说什么

这个状态表示对端已经发来了关闭请求,本端内核确认了它,但应用还没有调用关闭把连接释放掉。协议能把关闭报文送到,是否释放连接则取决于应用代码:连接用完没归还、异常分支漏了关闭、线程池阻塞导致处理停滞,都会让连接停在这个状态。因此大量堆积明确指向本端应用,而不是网络。排查方向是从连接找到进程,再回到代码里核对连接的生命周期管理。

基本信息

含义对端已关闭,本端应用尚未关闭连接
责任方本端应用,协议层面没有问题
查看命令ss -tan state close-wait 或加进程参数一起看
关注指标数量随时间的变化趋势,而不是单点数量
常见成因连接未归还、异常分支漏关闭、线程阻塞

典型使用场景

  • 排查连接泄漏:连接数持续增长且停在该状态
  • 定位到具体进程:按连接找到占用方
  • 核对代码缺陷:确认超时处理与异常分支是否归还连接
  • 评估修复效果:调整代码后观察数量是否回落
  • 区分网络与应用问题:把状态归属明确到应用侧

排查步骤

排查步骤
ss -tan state close-wait | wc -l                       # 看总量
ss -tanp state close-wait | head -30                   # 带进程查看
ss -tanp state close-wait | awk '{print $6}' | sort | uniq -c | sort -rn   # 按进程统计
# 结合进程与代码核对:连接获取与归还是否成对、异常路径是否关闭
jstack <pid> 2>/dev/null | grep -i -A5 'waiting' | head -40   # 线程是否阻塞在等待

状态归属对照

状态含义责任方
CLOSE-WAIT对端已关闭,本端未关闭本端应用未释放连接
FIN-WAIT-1本端已发关闭请求,等待确认本端主动关闭,正常过程
FIN-WAIT-2本端已确认,等待对端关闭对端应用未及时关闭
TIME-WAIT连接已关闭,等待超时结束主动关闭方,正常机制
LAST-ACK等待对端确认关闭本端主动关闭的最后阶段
ESTABLISHED连接正常存活看数量是否与业务预期一致
这个状态属于本端责任:网络只能负责把关闭报文送到,收到之后是否关闭连接完全由应用决定。把它归因于网络是这类问题里最常见的误判。
连接数持续增长会耗尽文件描述符与内存,最终表现为无法新建连接与响应变慢。发现趋势性增长就应尽快处理,而不是等到业务报错。

关联资源核对

关联资源核对
ls /proc/<pid>/fd 2>/dev/null | wc -l      # 进程打开的文件描述符数量
cat /proc/<pid>/limits | grep -i 'open files'   # 上限值,与当前数量对比
ss -tanp | grep <pid> | wc -l              # 该进程的连接总数

判读要点

  • 数量稳定在较低水平属于正常,持续单调上升才是泄漏特征
  • 同一进程的连接全部停在该状态时,优先核对连接池归还逻辑
  • 超时与重试路径最容易被忽略,异常分支未关闭连接是高频成因
  • 线程阻塞在等待外部资源时也会造成该状态堆积,需要看线程栈确认

易错点

  • 把该状态归因于网络或对端,实际责任在本端应用未调用关闭
  • 只看单点数量不看趋势,错过了泄漏的早期信号
  • 忽略异常分支与超时路径未归还连接,修复后问题复发
  • 线程阻塞造成的堆积被当成连接泄漏,排查方向偏差
  • 连接数接近文件描述符上限才发现,已出现无法新建连接的故障

数据来源与参考

  • RFC 9293(CLOSE-WAIT)
  • Linux ss 手册
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌