TCP服务端连接未释放问题

作者: | 更新日期:

遇到一个神秘的问题:客户端与服务端的连接不一致。

本文首发于公众号:天空的代码世界,微信号:tiankonguse

零、背景

上篇文章《TCP服务端主动断开连接问题》介绍了我工作中遇到的一个 TCP 相关的问题。

而在文末,我提到:

稍等,为啥以前连接没限制现在限制了?
还有我怎么记得连接被断开的时候,去转发机和接口机分别执行了netstat命令,看到的数据怎么不一致呢?
它们之间又有什么不可告人的秘密呢?

这篇文章就来揭开这个不可告人的秘密。

一、现象

我发现客户端与服务端的连接在频繁断开后,分别使用netstat在客户端和服务端查看了连接情况。

客户端:没有连接(已经是root用户了)。

对于服务端,由于只有一个进程,于是我使用lsof来精确查看进程的连接。
确认这个进程存在四个长连接(netstat一样的,这里为了更精确)。

然后我就疑惑了,不科学呀,怎么可能这样呢?

二、分析问题

虽然理论上不可能发生这样的事情,但是发生了,那肯定是所谓的“理论”是有缺陷的。

那什么是 TCP 连接呢?

对于服务端,好像也就是一个FD而已。
FD对应的连接信息储存在系统内核中,各种状态的变化都是由系统内核来控制的。

所以,正常情况下,客户端异常断开连接,服务端收到FIN后就不可能是ESTABLISHED

那既然客户端连接不存在了,服务端依旧是ESTABLISHED,那说明服务端没有收到客户端的FIN,或者客户端临死前没来得及发送FIN

那什么时候会发生这样的情况呢?
断电 与 网络异常一段时间,甚至是网线挖断。

这样就解释通了。

由于连接就是一个FD,内核没收到任何客户端的包,就不可能主动修改连接的状态。
所以客户端连接断了,FIN没到服务端的时候,就会发生这种情况。

三、解决问题

这个问题总结一下,其实就是一端死了,另一端没感知到。

那对应的解决方法也就简单了,大概分两类。

1、定时探测一下连接是否正常。
2、保存连接最近一次通信时间,定时清理很久没使用的连接。

对于第一类方案,又可以细分为两个方法。

1、系统内核级别解决,即所谓的keeplive选项。
2、业务自己实现,即所谓的心跳。

这样看来,就有三种方法了。

这三个方法各有优缺点,大家可以根据自己的场景来选择吧。

四、最后

神奇,本来是“理论”上不可能的事情,一分析,发现还真可能了。

而上篇文章提的问题也可以解释了。

为啥以前连接没触发限制现在被限制了?

由于服务端连接本来是够的,会随着偶尔事件变得无效,等这样的事情多了,就把服务端的连接消耗完了,导致某些客户端连接不上服务端。

你遇到过什么神奇的关于 TPC 的问题恩?

-EOF-

本文公众号:天空的代码世界
个人微信号:tiankonguse
公众号ID:tiankonguse-code

本文首发于公众号:天空的代码世界,微信号:tiankonguse
如果你想留言,可以在微信里面关注公众号进行留言。

关注公众号,接收最新消息

tiankonguse +
穿越