目录
1.为什么要设计心跳机制?
因为:
场景 | 问题 |
移动网络、4G/5G | 连接容易断(基站切换/信号弱) |
设备异常掉电 | 服务器不知道 |
网络设备(路由器、运营商) | 会主动断开空闲连接 |
如果没有心跳 ➔ 服务器会一直以为设备还在线,造成假连接、资源泄漏!
2.心跳机制设计原则
2.1 心跳间隔设置
-
实时性要求:
-
人联网设备(如智能手表):心跳间隔 5~40秒(高实时性)。
-
物联网设备(如环境传感器):心跳间隔 1~5分钟(低功耗优先)。
-
参考阿里云/腾讯云推荐:300~1200秒(适用于高可靠性平台)。
-
-
动态调整: 根据网络状况动态调整心跳间隔(如弱信号时缩短间隔,空闲时延长间隔)。
2.2 超时与重试机制
-
超时时间:
-
网络延迟较高时(如跨境连接):超时时间设为 3~5秒。
-
本地网络:超时时间设为 1~2秒。
-
-
重试策略:
-
最大重试次数:3~5次(避免永久阻塞)。
-
指数退避重试:首次失败后等待1秒,第二次2秒,第三次4秒……
-
2.3 双向心跳机制
-
客户端主动发送心跳:确保服务器知道设备在线。
-
服务器收到后更新最后活跃时间
-
服务器反向心跳:服务器定期向客户端发送探测包,验证双向连接。如果超过设定时间未收到心跳 ➔ 关闭连接!
2.4 协议兼容性
-
协议版本号:新增协议字段支持未来扩展(如新增心跳频率配置)。
-
保留字段:预留字段用于动态调整心跳参数(如
reserved
字段)。
3.心跳消息协议设计(推荐)
延续咱们之前的自定义TCP协议,我们可以规定:
-
Type字段 =
0x01
➔ 表示心跳包 -
Payload 可以为空,或者带一些简单状态信息(电量、信号强度)
心跳消息示例(很轻量):
+----------------+
| Magic Number |
| Version |
| Flags |
| Type = 0x01 | // 心跳类型
| SeqNum |
| DeviceID长度 |
| Payload长度 |
| DeviceID |
| Payload(可空) |
+----------------+
4. 实战方案—心跳机制实现
4.1 服务器端心跳超时检测(Netty实现)
(1)开启 Netty 的 Idle检测器
Netty已经内置了一个强大的空闲检测器 —— IdleStateHandler
!
// 在pipeline中添加IdleStateHandler
pipeline.addLast(new IdleStateHandler(60, 0, 0, TimeUnit.SECONDS));
// 读超时60秒
解释:
-
60秒内没有读到任何数据,触发读超时事件
-
我们可以在 handler 中捕捉这个超时,做断开处理
(2)自定义心跳处理器
public class HeartbeatHandler extends ChannelInboundHandlerAdapter {
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
IdleStateEvent event = (IdleStateEvent) evt;
if (event.state() == IdleState.READER_IDLE) {
// 读超时了
System.out.println("设备心跳超时,主动关闭连接:" + ctx.c