心跳机制
心跳机制时,发送心跳包后判断设备是否离线
等待响应
发送心跳包后,需要等待对方设备的响应。可以设置一个合理的超时时间,如果在这个时间内没有收到响应,则可能表明对方设备有问题。
超时处理
如果在设定的超时时间内没有收到响应,应该认为对方设备可能离线或出现故障。这时,可以采取进一步的措施,如重试发送心跳包、记录日志、发送告警、尝试重新建立连接等。
重试机制
在确定对方设备离线之前,可以实施一定的重试机制。例如,连续几次心跳包均未得到响应后才判断为离线。这有助于避免因网络短暂抖动而错误地判断设备离线。
心跳包的响应内容
心跳响应不仅是一个简单的确认,有时可以包含设备的状态信息。通过分析这些信息,可以更准确地判断设备的健康状况。
多点检测
如果应用场景允许,可以从多个节点发送心跳包,以增加检测的可靠性。如果所有节点都无法接收到响应,那么可以更确定地判断设备离线。
整合监控系统
在大型系统中,心跳检测通常与监控系统整合,以实现更全面的状态监控和告警机制。
Netty保活机制
TCP层面的保活机制
TCP 协议本身提供了一个保活机制,通过在长时间未收到数据时向对端发送探测报文,以检测连接的状态。在 Netty 中,可以通过设置 childOption(ChannelOption.SO_KEEPALIVE, true) 来启用 TCP 层面的保活机制。
TCP长连接下,客户端和服务器若长时间无数据交互情况下,若一方出现异常情况关闭连接,抑或是连接中间路由出于某种机制断开连接,而此时另一方不知道对方状态而一直维护连接,浪费系统资源的同时,也会引起下次数据交互时出错。为了解决此问题,引入了TCP KeepAlive机制(并非标准规范,但操作系统一旦实现,默认情况下须为关闭,可以被上层应用开启和关闭)。其基本原理是在此机制开启时,当长连接无数据交互一定时间间隔时,连接的一方会向对方发送保活探测包,如连接仍正常,对方将对此确认回应。
TCP KeepAlive参数
KeepAlive为操作系统层面的参数.
tcp_keepalive_time (integer; default: 7200; since Linux 2.2)
在TCP保活打开的情况下,最后一次数据交换到TCP发送第一个保活探测包的间隔,即允许的持续空闲时长,或者说每次正常发送心跳的周期,默认值为7200s(2h)。
tcp_keepalive_probes (integer; default: 9; since Linux 2.2)
在tcp_keepalive_time之后,最大允许发送保活探测包的次数,到达此次数后直接放弃尝试,并关闭连接,默认值为9(次)。
tcp_keepalive_intvl (integer; default: 75; since Linux 2.4)
在tcp_keepalive_time之后,没有接收到对方确认,继续发送保活探测包的发送频率,默认值为75s。
sysctl net.ipv4.tcp_keepalive_time sysctl net.ipv4.tcp_keepalive_intvl sysctl net.ipv4.tcp_keepalive_probes
设置keepalive参数
vi /etc/sysctl.conf # 数据交互空闲600秒后发送保活数据 net.ipv4.tcp_keepalive_time=600 # 如果没有收到对方确认,继续发送保活探测包,间隔为60秒 net.ipv4.net.ipv4.tcp_keepalive_intvl=60 # 最大允许发送保活探测包的次数,到达此次数后直接放弃尝试,并关闭连接 net.ipv4.net.ipv4.tcp_keepalive_probes=20 cat /etc/sysctl.conf # 刷新配置 sysctl -p
查看TCP连接
netstat -anutp
参数含义:
-a 显示所有
-n 以ip形式显示当前建立的有效连接和端口
-u 显示UDP协议
-t 显示TCP协议
-p 显示对应PID与程序名
TCP KeepAlive报文格式
TCP KeepAlive探测报文是一种没有任何数据,同时ACK标志被置上的报文,报文中的序列号为上次发生数据交互时TCP报文序列号减1。比如上次本端和对端数据交互的最后时刻,对端回应给本端的ACK报文序列号为 N(即下次本端向对端发送数据,序列号应该为N),则本端向对端发送的保活探测报文序列号应该为 N-1。
TCP KeepAlive机制 的作用 是检测连接的有无(死活),但无法检测连接是否有效,如断网的时候。“连接有效”的定义 = 双方具备发送和接收消息的能力
KeepAlive机制无法代替心跳机制,需要在应用层自己实现心跳机制以检测长连接的有效性,从而高效维持长连接
Keep-Alive机制不会强制切断连接,如果连接存在但是一直不发生数据交互。Keep-Alive不会切断连接。而应用层实现的心跳检测 heartbeat_check 即便连接存在,但不产生数据交互的情况下,依然会强制切断连接。
IdleStateHandler
Netty 提供了一个名为 IdleStateHandler 的处理器,用于在一段时间内没有读取到数据或写入数据时触发事件。你可以通过将 IdleStateHandler 添加到 ChannelPipeline 中来实现自定义的空闲状态处理逻辑。这样就可以及时地检测连接的空闲状态,执行相应的处理操作,比如发送心跳消息或关闭连接。
定时任务
除了 IdleStateHandler 外,你还可以使用 Netty 提供的定时任务功能来实现保活机制。通过定时任务,你可以周期性地向对端发送心跳消息,以检测连接的状态。这种方式更加灵活,可以根据实际需求自定义心跳间隔和心跳消息内容。