一次 Netty 代码不健壮导致的大量 CLOSE_WAIT 连接原因分析

线上Dubbo服务出现大量CLOSE_WAIT状态连接,原因是Netty在处理TCP连接时,由于内存溢出(OOM)导致无法注册事件且未关闭连接。分析发现,Netty在accept连接并注册事件时,如果出现异常,连接保持打开状态,无法响应FIN包。通过模拟复现问题,提出在异常处理中关闭连接的解决方案。
摘要由CSDN通过智能技术生成

背景

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

首先从 TCP 的角度看一下 CLOSE_WAIT

CLOSE_WAIT 状态出现在被动关闭方,当收到对端 FIN 以后回复 ACK,但是自身没有发送 FIN 包之前。

所以这里的原因就很清楚了,出现永远存在的 CLOSE_WAIT 的连接是因为,收到了对端的 FIN 包,但是自己一直没有回复 FIN。通过抓包确实验证了这个的想法。

问题就落在了为什么没有回复 FIN,这是一个健康检查探测的请求,三次握手成功以后,探测服务会马上发送 FIN,理论上 dubbo 服务也会立刻回复 FIN,但是没有任何反应。

对于 dubbo 底层使用的 netty 来说,它就是一个普通的 tcp 服务端,无非就这几步:

  1. bind、listen
  2. 注册 accept 事件到 epoll
  3. epoll_wait 等待连接到来
  4. 连接到来时,调用 accept 接收连接
  5. 注册新连接的 EPOLLIN、EPOLLERR、EPOLLHUP 等事件到 epoll
  6. epoll_wait 等待事件发生

如果是没有发送 fin,有几个比较明显的可能原因。

  1. 第 2 步没有做,压根没有注册 accept 事件(可以排除,肯定有注册)
  2. 第 4 步没有做,连接到来时,netty 「忘了」调用 accept 把连接从内核的全连接队列里取走。这里的「忘」可能是因为逻辑 bug 或者 netty 忙于其他事情没有时间取走,这个待会验证
  3. 第 5 步没有做,取走了连接,三次握手
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值