背景
我们线上有一个 dubbo 的服务,出现大量的 CLOSE_WAIT 状态的连接,这些 CLOSE_WAIT 的连接出现以后不会消失,这就有点意思了,于是做了一下分析记录如下。
首先从 TCP 的角度看一下 CLOSE_WAIT

CLOSE_WAIT 状态出现在被动关闭方,当收到对端 FIN 以后回复 ACK,但是自身没有发送 FIN 包之前。
所以这里的原因就很清楚了,出现永远存在的 CLOSE_WAIT 的连接是因为,收到了对端的 FIN 包,但是自己一直没有回复 FIN。通过抓包确实验证了这个的想法。

问题就落在了为什么没有回复 FIN,这是一个健康检查探测的请求,三次握手成功以后,探测服务会马上发送 FIN,理论上 dubbo 服务也会立刻回复 FIN,但是没有任何反应。
对于 dubbo 底层使用的 netty 来说,它就是一个普通的 tcp 服务端,无非就这几步:
- bind、listen
- 注册 accept 事件到 epoll
- epoll_wait 等待连接到来
- 连接到来时,调用 accept 接收连接
- 注册新连接的 EPOLLIN、EPOLLERR、EPOLLHUP 等事件到 epoll
- epoll_wait 等待事件发生
如果是没有发送 fin,有几个比较明显的可能原因。
- 第 2 步没有做,压根没有注

文章详细分析了一次由于Netty代码不健壮导致的大量CLOSE_WAIT连接问题。当收到对端FIN后,服务端未发送FIN,通过排查确认Netty在接收到连接并调用accept后,未能注册新连接事件,可能是由于线程OOM异常。通过模拟复现证实了这一假设,并提出在异常处理中关闭连接的解决方案。
最低0.47元/天 解锁文章
1万+

被折叠的 条评论
为什么被折叠?



