Netty——心跳机制与断线重连
创始人
2024-06-03 07:15:18
0

心跳机制与断线重连

    • 心跳机制
      • IdleStateHandler
      • 客户端
      • 服务端
      • 测试
        • 正常情况
        • 异常情况
      • 总结
    • 断线重连

为了保证系统的稳定性,心跳机制和断线重连可是必不可少的,而这两个在Netty中也是非常好实现的

心跳机制

我们以客户端发送心跳为例,平时我们的心跳实现方式可能是搞个定时器,定时发送是吧,但是在Netty中却不一样,心跳被称为空闲检测,因为心跳的最主要作用就是判断是否存活、是否假死等情况,所以Netty中并不是定时发送,而是空闲的情况下才发送,空闲指的是一段时间内无读写事件的发生,也就是没有信息接收和信息发送啦,这时候我就要检测一下了

所以Netty的机制就是通过监测一段时间内是否有信息的读、写发生,然后产生一个事件,我们可以处理这个事件来达到我们的目的

IdleStateHandler

心跳与其他的数据处理Handler一样,都是建立连接后的数据处理,所以同样都是处理管道中的,IdleStateHandler就是Netty帮我们封装好了的处理类,我们可以直接使用并将它放入管道中,就可以自动检测一段时间内是否有读、写发生了,常用的构造有4个参数:

  • readerIdleTime:读事件检测,该时间内没有信息读取就会产生一个读信息的事件
  • writerIdleTime:写事件检测,该时间内没有信息发送就会产生一个写信息的事件
  • allIdleTime:读写事件检测,该时间内没有信息发送或者读取就会产生一个读写信息的事件
  • unit:时间单位
public IdleStateHandler(long readerIdleTime, long writerIdleTime, long allIdleTime, TimeUnit unit) {this(false, readerIdleTime, writerIdleTime, allIdleTime, unit);
}

使用

// 管道中直接添加
// 时间配置为0则代表不检测对应事件
channel.pipeline().addLast(new IdleStateHandler(5,0,0, TimeUnit.SECONDS))

触发的事件类型

  • IdleState.READER_IDLE:读信息的事件
  • IdleState.WRITER_IDLE:写信息的事件
  • IdleState.ALL_IDLE:读写信息的事件

举个例子:假设我们是客户端主动发送心跳,那客户端就要检测一段时间内是否有写信息的操作,如果没有就会触发IdleState.WRITER_IDLE事件,那我们监听这个事件,就做出自己的处理,那就是主动发送心跳包嘛

下面我们就以客户端发送心跳包为例!

客户端

像上面那样直接使用IdleStateHandler,那还需要单独写一个事件处理的类,所以这里我们直接继承IdleStateHandler

ClientHeartbeatHandler 如下:

我们设置5秒,5秒内没有写过信息,我们就发送心跳包(这里消息很随意,图方便)

@Slf4j
public class ClientHeartbeatHandler extends IdleStateHandler {// 设置写事件为5s// 如果5s没有写事件发生 就会触发下面的IdleStateEventprivate static final int WRITE_IDLE_TIME = 5;public ClientHeartbeatHandler() {super(0, WRITE_IDLE_TIME, 0, TimeUnit.SECONDS);}@Overrideprotected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) throws Exception {// 指定时间内没有写事件发送 就会触发 IdleState.WRITER_IDLE 类型事件// 我们就可以对该连接进行处理 主动发送心跳if(evt.state()== IdleState.WRITER_IDLE){log.info("{} 秒内没有发送数据,再不发送小心和服务端断开连接", WRITE_IDLE_TIME);ctx.writeAndFlush(new NettyMsg(ServiceCodeEnum.TEST_TYPE,"我还活着,不要断开连接"));}}
}

NettyClient

管道中加入这个即可,注意要放在编解码之后

在这里插入图片描述

服务端

基本跟客户端一样,但是由于是客户端给我发心跳,所以服务端要监测读事件

ServerHeartbeatHandler

这里我们设置10s,一般会更多因为要给客户端一些容忍度,适量就好,一旦没满足就和客户端断开连接

@Slf4j
public class ServerHeartbeatHandler extends IdleStateHandler {// 设置读取事件为10s// 如果10s没有读事件发生 就会触发下面的IdleStateEventprivate static final int READER_IDLE_TIME = 10;public ServerHeartbeatHandler() {super(READER_IDLE_TIME, 0, 0, TimeUnit.SECONDS);}@Overrideprotected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) throws Exception {// 指定时间内没有读事件发送 就会触发 IdleState.READER_IDLE 类型事件// 我们就可以对该连接进行处理 这里是直接关闭if(evt.state()== IdleState.READER_IDLE){log.info("{} 秒内没有读取到数据,关闭连接", READER_IDLE_TIME);ctx.channel().close();}}
}

NettyServer

在这里插入图片描述

测试

正常情况

服务端

在这里插入图片描述

客户端

在这里插入图片描述

异常情况

我们将客户端心跳拉长

在这里插入图片描述

可以发现时间一到自动断连

在这里插入图片描述

总结

这里是以客户端发送心跳为例,如果是以服务端发送心跳也是一样,主要就是对读写事件的监听,然后做出相应处理,上面其实是很随意的哈,正常情况下心跳包是会用专门的消息类型的,而且服务端也需要做出应答的,心跳应答也会有对应的消息类型

断线重连

这个就很简单了,肯定是断线后,客户端发起重连嘛,就是在客户端检测到连接断开的时候,重新连接就好了

ClientHeartbeatHandler加上一段:

在这里插入图片描述

看看效果,客户端心跳时间还是12s哈

在这里插入图片描述

能这么随意吗?当然不行啊,别学我,正常会搞多次重连,而且谨慎起见,每次重连还可以加一个时间的间隔,可以学一下nacos里面的高级玩法,随着重连次数的增加,间隔重试的时间也随之增加,比如:

第一次重连是4s,第二次重连是8s,第三次是16s,以此类推
也就是设置重连间隔时间基数为4s,每尝试一次,左移一位(4<<1),连接成功后基数复位为4s需要设置最大重试次数,最长间隔时间(一直左移后面会很长时间,所以要设置一个上限,超过了就以上限为准)

伪代码如下

    @Overridepublic void channelInactive(ChannelHandlerContext ctx) throws Exception {log.info(ctx.channel().remoteAddress() + " 已断开连接,开始重连");int maxRetryNum=6; //最大重连次数int maxRetryTime=60; // 最大重连时间int baseRetryTime=4; // 间隔时间基数// 开始重连for (int i = 1; i <= maxRetryNum; i++) {log.info("第{}次重连,间隔{}s后开始",i,baseRetryTime > maxRetryTime ? maxRetryTime:baseRetryTime);ctx.channel().eventLoop().schedule(()->{// 重连操作// .......// 判断是否超过隔间上限},baseRetryTime > maxRetryTime ? maxRetryTime:baseRetryTime,TimeUnit.SECONDS);// 左移扩大一倍baseRetryTime = baseRetryTime << 1;}log.info("这么多次重连都不行寄了吧");}

伪代码哈,伪代码!

结果如下

建立连接后,手动关闭服务端,可以看到重连了6次,每次间隔时间翻倍,达到间隔时间上限后,就以上限的时间为准
在这里插入图片描述

相关内容

热门资讯

初夏的诗句(花草) 初夏的诗句(花草)  春天随着落花走了,夏天披着一身的绿叶儿在暖风儿里跳动着来了。这也激活着花草树木...
辛弃疾《西江月遣兴》拼音 辛弃疾《西江月遣兴》拼音  《西江月遣兴》是宋朝诗人的辛弃疾著作,以下就是小编分享辛弃疾《西江月遣兴...
写秋季景色的诗句 写秋季景色的诗句  写秋季景色的诗句有哪些?哪些句子是描写秋季景色的呢?下面小编就给大家分享整理了一...
徐志摩《私语》原文赏读 徐志摩《私语》原文赏读  秋雨在一流清冷的秋水池,  一颗憔悴的秋柳里,  一条怯懦的秋枝上,  一...
南轩,南轩戴叔伦,南轩的意思... 南轩,南轩戴叔伦,南轩的意思,南轩赏析 -诗词大全 南轩 作者:戴叔伦朝代:唐体裁:五律 ...
“此生谁料,心在天山,身老沧... “此生谁料,心在天山,身老沧洲!”出自宋代文学家陆游的词作《诉衷情·当年万里觅封侯》诉衷情陆游当年万...
中秋节的诗句英文 有关中秋节的诗句英文锦集(精选5篇)  在平凡的学习、工作、生活中,说到诗句,大家肯定都不陌生吧,不...
苏轼写的古诗有哪些 苏轼写的古诗有哪些  苏轼,字子瞻,又字和仲,号东坡居士,世称苏东坡、苏仙。下面我们一起来看看苏轼写...
小学唐诗 小学唐诗  引导语:下面是小编为大家收集的小学唐诗60首,欢迎大家阅读。  1、江南 汉乐府  江南...
小学一到六年级古诗 人教版小学一到六年级古诗汇总  看到厚厚的一摞小学12册语文课本,小编的心中也是感慨万千,这些,与学...
寻找描写茶花的诗句 寻找描写茶花的诗句  茶花是中国传统的观赏花卉,“十大名花”中排名第八,亦是世界名贵花木之一,在诗人...
辛弃疾诗词集 辛弃疾诗词集  引言:辛弃疾南宋豪放派词人、将领,有“词中之龙”之称。与苏轼合称“苏辛”,与李清照并...
花和雨的诗句 花和雨的诗句  花自飘零水自流。一种相思,两处闲愁。以下是花和雨的诗句,欢迎阅读!  花和雨的诗句 ...
风花雪月的优美诗句 风花雪月的优美诗句  风的诗句:  1、《春晓》  唐·孟浩然  春眠不觉晓,处处闻啼鸟。  夜来风...
写哪些赞美老师的诗句 写哪些赞美老师的诗句  刻在木板上的名字未必不朽,刻在石头上的名字也未必流芳百世;老师,您的名字刻在...
离别惆怅的诗句是 离别惆怅的诗句是  惆怅就是因为心中郁闷而不知道该干什么,忧伤和悲哀是表示的一种心理状态,而惆怅是强...
冰心诗集《繁星》全文(2) 冰心诗集《繁星》全文  八十九  花儿低低的对看花的人说  "少顾念我罢  我的朋友!  让我自己安...
船字开头的诗句 船字开头的诗句  船,指的`是:利用水的浮力,依靠人力、风帆、发动机(如蒸气机、燃气涡轮、柴油引擎、...
赞美端午节的优美诗句 赞美端午节的优美诗句  端午节起源于春秋战国,距今已有两千多年。关于端午节的'诗句有哪些呢?  1、...
春天的诗句 春天的诗句(通用205句)  在日复一日的学习、工作或生活中,大家都经常接触到诗句吧,诗句节奏上鲜明...