TCP 的 keepalive 机制,如果在一段时间内,客户端和服务端之间没有任何报文传输,那么 TCP 的保活机制就会开始起作用。他会每隔一定的时间间隔,发送一个探测报文,如果连续的探测报文都没有得到响应,则认为当前的 TCP 连接已经死亡,操作系统便将错误信息通知给上层应用程序。
内核提供了一些参数可以用来设置保活机制。包括:保活时间、保活探测的次数、保活探测的时间。
net.ipv4.tcp_keepalive_time=7200
表示保活时间是 7200 秒,也就是 2 小时内如果没有任何连接相关的报文,就会启动保活机制net.ipv4.tcp_keepalive_intvl=75
每次检测间隔为 75 秒net.ipv4.tcp_keepalive_probes=9
表示检测 9 次无响应,则认为对方是不可达的,从而中断本次的连接
也就是说,在 Linux 系统中,默认配置下。最少需要经过 7875 秒才可以发现一个已经死亡的连接。
内核中 TCP 协议栈发送探测报文的情况:
- 如果对端程序是正常工作的。当 TCP 保活的探测报文发送给对端,对端会正常响应,这样 TCP 保活时间会被重置,等待下一个 TCP 保活时间的到来。
- 如果对端主机崩溃,或对端由于其他原因导致报文不可达。当 TCP 保活的探测报文发送给对端后,没有响应,连续一定次数,达到保活探测次数后,TCP 会报告该 TCP 连接已经死亡。
注意:TCP 的保活机制需要设置 socket 接口的 SO_KEEPALIVE 选项才能够生效。
TCP 保活机制探测的时间也太长了?
TCP 保活机制是 TCP 协议栈实现的,他是所有基于 TCP 传输协议程序的一个兜底方案。其实我们应用层也可以自己实现一套探测机制,可以在较短的时间内,探测到对方是否存活。
比如,web 服务软件一般都会提供 keepalive_timeout
参数,用来指定 HTTP 长连接的超时时间。如果设置了 HTTP 长连接的超时时间是 60 秒,web 服务软件就会启动一个定时器,如果客户端在完后一个 HTTP 请求后,在 60 秒内都没有再发起新的请求,定时器的时间一到,就会触发回调函数来释放该连接。