在开始这边文章之前,我问了自己几个问题,如下所示:
下面我们来一个个问题看下去。
1. 为什么我们需要保活消息?
对于TCP链接来说,他们之间一旦建立了连接,那么可以一直没有消息通讯。TCP连接的双方都没有向对方发送数据,则在两个TCP模块之间不交换任何信息。
只要两端的主机没有被重启,则连接依然保持建立,不管中间路由器可以崩溃和重启,还是电话线被挂断再连通。这意味着我们可以启动一个客户与服务器建立一个连接,然后离去数小时、数天、数个星期或者数月,而连接依然保持。
这对于客户端来说,倒还好一点,毕竟不会有那么多的连接被占用,对于服务器来说,就是一个很糟糕的事情,这种连接无疑是一种僵尸连接,平白无辜的占用着服务器的资源,一旦这种连接非常多,服务器往往会因为连接数量的限制,导致没有办法接入新的客户端。
这个时候,其实就需要一种定时探测对端连接是否还存活的机制存在,如此以来彼此都能知道对方的状态,是否还能继续使用。
这种机制,对于TCP来说,就是TCP的保活机制。
2. 保活消息有什么优缺点?
优点:
1.在连接两个端系统的网络出现临时故障的时候,保活选项会引起一个 实际上很好的连接终止 。
例如,如果在一个中间路由器崩溃并重新启动时发送保活探查,
那么TCP会认为客户的主机已经崩溃,而实际上所发生的并非如此。
2.保活功能主要是为服务器应用程序提供的。
服务器应用程序希望知道客户主机是否崩溃,从而可以代表客户使用资源,及时回收这些资源。
缺点:
保活并不是TCP规范中的一部分。Host Requirements RFC提供了3个不使用保活定时器的理由:
1)在出现短暂差错的情况下,这可能会使一个非常好的连接释放掉;
2)它们耗费不必要的带宽;
3)在按分组计费的情况下会在互联网上花掉更多的钱。
3. 保活消息是怎么使用的?
保活消息一般设置在服务器端,客户端往往不会设置,除非特别有必要的时候才会设置。
1)保活机制是由一个保活计时器实现的。当计时器被激发,连接一段将发送一个保活探测报文,另一端接收报文的同时会发送一个ACK
作为响应。
具体实现上有以下几个相关的配置:
保活时间:默认7200秒(2小时)
保活时间间隔:默认75秒
保活探测数:默认9次
查看Linux系统中TCP保活机制对应的系统配置如下(不同系统实现可能不同):
$: /proc/sys/net/ipv4$ cat tcp_keepalive_time
7200
$: /proc/sys/net/ipv4$ cat tcp_keepalive_intvl
75
$: /proc/sys/net/ipv4$ cat tcp_keepalive_probes
9
2)功能描述:
如果一个给定的连接在两个小时之内没有任何动作,则服务器就向客户发送一个探查报文段。客户主机必须处于以下4个状态之一。
备注:服务器不用关注客户主机被关闭和重新启动的情况(这指的不是主机崩溃)
1.当系统被操作员关闭时,所有的应用进程也被终止(也就是客户进程),
这会使客户的TCP在连接上发出一个FIN。
2.接收到FIN将使服务器的TCP向服务器进程报告文件结束,
使服务器可以检测到这个情况。
参考文档:
http://docs.52im.net/extend/docs/book/tcpip/vol1/23/
https://klose911.github.io/html/tii/tcp-keep-alive-alarm
https://juejin.cn/post/6844903878819840008