ss -s 显示 CLOSE_WAIT 有三千多条,端口和内存缓慢上涨,重启应用十分钟后又堆回来,对端说连接早就断开了,问题显然在本地。第一次遇到会往复杂处想,其实漏掉的多是个小前提。

ss -tan state close-wait | wc -l
ss -tan state close-wait | head -20
ss -s
lsof -p <pid> | grep -c TCP

对端发了 FIN 之后本端没有调用 close,socket 一直停在 CLOSE_WAIT,多半是异常分支没释放连接或者连接池借出后忘了归还,连接越积越多,最终耗尽端口。这一点先确认清楚,后面就不用反复试。

「CLOSE_WAIT 堆积」这个问题文档写得含糊,实际行为以当前版本为准,别照旧版本的结论套。把复现步骤压到三条以内,交给同事也能跑出来,才算真的定位清楚。

改动写完就同步给同事,下一个人踩同一个坑,成本还是你的。

具体做法是,按时统计 CLOSE_WAIT 的对端地址看集中在哪个下游 先缩小范围;用 lsof 看这些 fd 属于进程里哪个模块或连接池 再看代码路径;在异常分支补 try finally 或者换用上下文管理器 确保一定会释放。

改完照着核一遍,CLOSE_WAIT 回落到两位数 并且不再随请求量线性增长 压测十分钟看曲线。

作者 9823189