浅谈 tcp 保活机制

政采云技术团队.png

拍拍.png

一、简单介绍TCP连接

​ 一个TCP连接由源IP地址、源端口、目标IP地址、目标端口这四元组来唯一标识,连接的建立需要经历“三次握手”,而连接的释放也需要经历“四次挥手”,并且“四次挥手”是需要由服务端或客户端其中一方主动发起的。

​ 那么问题来了,要是一个已经创建好的TCP连接,即使长时间都没有一点数据交换,那么它也会一直存活于双方吗?答案是肯定的,这意味着我们启动一个客户端进程,与服务器端建立连接后,然后在理想状态下(TCP连接的两端的主机没有被重新启动或更换IP地址)离开几个小时、几天、几星期、几个月甚至更长时间,这个连接依然会保持。

二、保活机制

2.1 TCP保活机制也叫TCP keepalive,它的初衷主要是为了解决两个问题:

​ 1、客户端和服务器需要知道对端状态,以及自己是否该断开连接(因为TCP连接建立后,连接两端都有可能出现一些问题没来得及发起“四次挥手”就断开网络的情况,这时连接的另一端并不知道对端的情况,它会一直维护这个连接,长时间的积累会导致非常多的半打开连接,造成端系统资源的消耗和浪费。)

​ 2、而在另一些情况下,虽然应用进程之间没有任何数据交换,但仍然需要通过连接保持一个最小的数据流(因为网络连接中间可能会经过路由器、防火墙等设备,而这些设备有可能会对长时间没有数据交换的连接在连接信息表中删除,从而影响后续的报文传输。)

​ 保活机制默认关闭,每一端都可以通过设置套接字属性SO_KEEPALIVE来开启保活机制。

2.2实现原理:

​ 当一个 TCP 连接建立之后,开启 TCP keepalive 的一端会启动一个计时器,当这个计时器数值到达 0 之后(也就是经过 tcp_keepalive_time 时间后,当然每次传输数据都将重置计时器数值),会发送一个保活探测报文。探测报文不包含任何数据,或者包含一个无意义的字节,对方主机必须处于下表中的 4 个状态之一,己方则根据对端状态作不同处理。

image-20220711153405106.png

2.3保活机制的三个重要参数:

​ 1、tcp_keepalive_time

WeChat0a53c2bebda8c06ae385bf0f12a35ae9.png

​ 在 TCP 保活机制开启的情况下,最后一次数据交换到发送第一个保活探测包的间隔,linux 默认值为7200s

​ 2、tcp_keepalive_probes

WeChatec5ead017fddc993db979b71b8da25de.png

​ 在经过 tcp_keepalive_time 之后,没有接收到对方确认,继续发送保活探测包次数,linux 默认值为 9 次

​ 3、tcp_keepalive_intvl

WeChatd94c6338370c1d113ce7caaf1a8d692f.png

​ 在tcp_keepalive_time之后,没有接收到对方确认,继续发送保活探测包的发送频率,linux默认值为75s

​ 通过这三个参数我们可以得到,在linux系统中,默认需要经过 2 小时 11 分 15 秒才可以发现一个“死亡连接”。

​ tcp_keepalive_time+(tcp_keepalive_probes * tcp_keepalive_intvl)= 7875秒

2.4验证

​ 接下来我们来验证一下实际是否会像理论的那样有规律的发送探测报文,首先我们需要一个服务端开启了keepalive的服务,ssh服务满足条件,按默认值进行验证的话需要2个多小时,这可太久啦,所以我们可以手动修改这几个参数值来方便我们短时间内进行验证。

​ 2.4.1 通过echo 20 > /proc/sys/net/ipv4/tcp_keepalive_time将发送保活探测包的间隔改为20s,用sysctl -p刷新配置,然后打开Wireshark进行抓包,新建ssh远程连接后不进行数据传输,可以看到每隔20秒会有从服务端发送过来的Keep-Alive报文,以此证明参数生效。

WeChataf1e7ce44cdd9dbbe434c367b7d32653.png

​ 2.4.2 通过 echo 10 > /proc/sys/net/ipv4/tcp_keepalive_intvl 将发送频率修改为10秒, echo 2 > /proc/sys/net/ipv4/tcp_keepalive_probes 将发送次数修改为2次。为了模拟由于连接中断等异常导致探活报文收不到回应的场景,借助Linux iptables命令设置防火墙,阻断TCP探活报文的传输。以此将来自客户端的返回报文丢弃,这样就可以模拟服务器发送TCP keepalive探活报文后收不到回应报文的场景了。使用的命令为:sudo iptables -A INPUT -p tcp --sport $YOUR_CLIENT_PORT -j DROP,其中sport后面跟的是系统为客户端分配的端口号。由于ssh服务端是运行在Linux系统上的,ssh客户端和wireshark运行在本地MAC电脑上,因此利用上述iptables设置防火墙规则后,Wireshark仍能抓到所有服务端发出的探活报文以及客户端返回的应答报文,只是在Linux系统这一侧通过防火墙将应答报文丢弃了。

WeChatab70136893f5a6a9b2a4b72ed1dff7f9.png

​ 我们先通过netstat -nat命令查到服务端所有连接,并找到对应的 ssh 连接,可以得到在服务端给这个ssh连接分配的端口为 2181。然后我们使用上面的命令设置防火墙。再观察抓包情况。

WeChat9d87dc8d74a84ac464eddb9e41391575.png

服务器发送TCP keepalive探活报文后,一直收不到确认报文的返回,便隔 10 秒重新发送一个探活报文,即上文提到的服务器tcp_keepalive_intvl参数的设置。再等待 2 个tcp_keepalive_intvl时间间隔后,服务器仍未收到确认报文后,服务器发送了RST报文,以释放网络连接资源,这里的 2 次是由tcp_keepalive_probes设置的。在完成上述测试后,借助sudo iptables -F`命令清除所有的防火墙规则。

​ 至此,我们对这三个参数的功能验证也完成了。

三、保活机制的弊端

​ 1、在出现短暂的网络错误的时候,keepalive参数设置不合理(探测时间过于短暂)时有可能会使一个健康的连接断开;

​ 2、保活机制会占用不必要的流量;

四、思考:为什么有了保活机制,应用层还需要实现心跳机制呢?

​ 看了上面的介绍,不难看出保活机制可以感应到对端网络的异常,可以回收异常的连接,那么应用层之所以还需要实现心跳机制,我认为有以下几个原因:

​ 1、TCP keepalive只能判断连接是否存活,无法判断连接是否正常可用,当服务端出现异常的时候,客户端无法通过该机制感知到服务端进程是否阻塞或其他应用内死锁等异常。

​ 2、TCP keepalive是存在于传输层的,客户端与服务端之间可能会存在传输层之上的代理,如haproxy中的四层代理,这样只有传输层以上的流量才会被转发

五、TCP Keepalive HTTP Keep-Alive 的关系

​ 很多同学会把TCP KeepaliveHTTP Keep-Alive 这两个概念搞混淆。

HTTP keepalive是由应用层实现的,在HTTP/1.0中,默认使用的是短连接。浏览器每发起一次HTTP请求,就建立一个连接,但任务结束就中断连接。

​ 从 HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在请求头加上Connection:keep-Alive字段。

image-20220711170738515.png

所以总结一下两者的区别:

​ 1、HTTPKeep-Alive是为了让TCP连接活得更久一点,在发起多个http请求时能复用同一个连接,提高通信效率;

​ 2、TCPKeepAlive机制意图在于探测连接的对端是否存活,是一种检测TCP连接状况的机制。

​ 3、tcp具备双端连续收发报文的能力,开启了keep-alive的HTTP连接,由于协议本身的限制,服务端无法主动发起应用报文。

推荐阅读

CDH6.3.2 升级 Spark3.3.0 版本

从源码看 Lucene 的文档写入流程

ElasticSearch 文档分值 score 计算&聚合搜索案例分析

Label Studio+Yolov5 实现目标检测预标注(二)

招贤纳士

政采云技术团队(Zero),一个富有激情、创造力和执行力的团队,Base 在风景如画的杭州。团队现有 500 多名研发小伙伴,既有来自阿里、华为、网易的“老”兵,也有来自浙大、中科大、杭电等校的新人。团队在日常业务开发之外,还分别在云原生、区块链、人工智能、低代码平台、中间件、大数据、物料体系、工程平台、性能体验、可视化等领域进行技术探索和实践,推动并落地了一系列的内部技术产品,持续探索技术的新边界。此外,团队还纷纷投身社区建设,目前已经是 google flutter、scikit-learn、Apache Dubbo、Apache Rocketmq、Apache Pulsar、CNCF Dapr、Apache DolphinScheduler、alibaba Seata 等众多优秀开源社区的贡献者。如果你想改变一直被事折腾,希望开始折腾事;如果你想改变一直被告诫需要多些想法,却无从破局;如果你想改变你有能力去做成那个结果,却不需要你;如果你想改变你想做成的事需要一个团队去支撑,但没你带人的位置;如果你想改变本来悟性不错,但总是有那一层窗户纸的模糊……如果你相信相信的力量,相信平凡人能成就非凡事,相信能遇到更好的自己。如果你希望参与到随着业务腾飞的过程,亲手推动一个有着深入的业务理解、完善的技术体系、技术创造价值、影响力外溢的技术团队的成长过程,我觉得我们该聊聊。任何时间,等着你写点什么,发给 zcy-tc@cai-inc.com

微信公众号

文章同步发布,政采云技术团队公众号,欢迎关注

政采云技术团队.png