服务器出现大量 CLOSE_WAIT 怎么排查?和 TIME_WAIT 堆积有什么区别?
下面是一段教学用的模拟面试。
🧑💻 面试官:大量 CLOSE_WAIT,说明什么?
🙋♂️ 我:对端已经结束发送,本地还没完成关闭。
🧑💻 面试官:调小 TIME_WAIT 超时有用吗?
🙋♂️ 我:没有针对问题,状态原因不同。
🧑💻 面试官:只有访问一个外部接口的连接在增加,怎样找哪条代码没释放?收到 EOF 还能继续写吗?
CLOSE_WAIT 重点看「本地应用为什么没关闭」。TIME_WAIT 是关闭协议后的等待,不用同一套参数处理。
面试速答(60 秒版)
CLOSE_WAIT 表示本地收到对端 FIN,TCP 已确认,而本地应用尚未完成自己的关闭。持续积累时,应先检查 socket、响应流和连接对象是否正确释放。
TIME_WAIT 常见于主动关闭方完成相应关闭后,为处理迟到报文和确认可靠性保留一段时间。它不是同一种资源未释放问题。
排查 CLOSE_WAIT,我会按进程、远端和增长趋势定位,再检查 EOF、异常、超时及提前返回分支。HTTP 客户端还要区分响应体释放、连接池归还与底层关闭。
短暂状态可能正常,长期增加则要找生命周期漏洞。调 TIME_WAIT 参数,不能代替修本地遗漏的关闭。

图:CLOSE_WAIT 先查本地关闭。
知识点详解:收到关闭,应用为什么还没结束?
FIN 只表示一个发送方向结束
假设本地调用外部接口,对端先发 FIN。它表示对端不再发送新数据,不等于两个方向瞬间被强制关闭。
本地确认后可以进入 CLOSE_WAIT。应用读到 EOF 等结束信息,按协议处理剩余工作,再关闭。
TCP 可以半关闭,因此在允许状态与业务约定下,本地仍可能发送数据。这也是短暂 CLOSE_WAIT 不必代表错误的原因。状态含义见 RFC 9293。
持续增长,为什么指向本地生命周期?
读完忘关闭,或异常跳过释放,就可能长期保留连接。
假设只有下载接口的连接不断增加。先按 PID 找持有进程,再按远端统计,缩小到相应客户端。
检查正常完成、读超时、解析失败和提前返回时,响应有没有释放。连接池中,释放响应体通常是归还入口,但是否复用或关闭底层连接,要看库。
不能看到代码有一个 close,就认为所有路径覆盖。要明确资源从创建到结束归谁管理。
怎样排查,而不是先改参数?
Linux 可用 ss 筛选 close-wait,并在相应权限下查看进程,定义见 ss 手册。
记录数量、连接年龄、远端分布与增长速度,再关联超时、失败和文件描述符数量。
流量稳定但未释放连接持续增加,更支持泄漏线索;短暂出现又消失,可能是正常关闭窗口。在授权测试环境让对端提前关闭,覆盖正常、异常、超时,确认资源数量恢复。

图:追到持有资源的具体请求路径。
TIME_WAIT 为什么不能同样处理?
TIME_WAIT 常在主动关闭完成后保留协议状态。大量短连接可能形成大量 TIME_WAIT,即使应用正确关闭。
前者结合连接复用、建立速率和端口资源评估;CLOSE_WAIT 首先检查应用释放。
复杂关闭情形还要按状态机分析,例如同时关闭。不能把常见单方主动关闭的简化模型说成无条件规则。
面试官继续追问
重启后消失,证明什么?
证明进程资源被释放,提供生命周期线索。但没定位遗漏代码,可能重新出现。
服务端一定被动关闭吗?
不是。主动关闭由谁先发起决定,不由客户端/服务端身份固定。
增大描述符上限能解决吗?
只能延后耗尽。合理上限和泄漏修复分开处理。
面试速记卡
- CLOSE_WAIT:收到对端 FIN,等待本地关闭。
- 排查:进程、远端、趋势和异常释放路径。
- 客户端:响应体、池归还和 socket 生命周期分清。
- TIME_WAIT:协议等待,不等于同类泄漏。
- 修复:资源所有权清楚,正常异常都释放。
公司面试真题
这道题暂未收录可核验的公司真题来源。你可以先阅读本文解析,或浏览已收录的公司面试真题。
浏览公司面试真题 →