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
如果你想留言,可以在微信里面关注公众号进行留言。