【Netty】利用Netty实现心跳检测和重连机制

netty心跳机制和重连 netty心跳机制和重连 一、理论和概述 1、何为心跳 顾名思义, 所谓心跳, 即在 TCP 长连接中, 客户端和服务器之间定期发送的一种特殊的数据包, 通知对方自己还在线, 以确保 TCP 连接的有效性。 为什么引入心跳机制和其原理? 因为网络的不可靠性, 有可能在 TCP 保持长连接的过程中, 由于某些突发情况, 例如网线被拔出, 突然掉电等, 会造成服务器和客户端的连接中断. 在这些突发情况下, 如果恰好服务器和客户端之间没有交互的话, 那么它们是不能在短时间内发现对方已经掉线的. 为了解. 阅读详情

一、前言

  心跳机制是定时发送一个自定义的结构体(心跳包),让对方知道自己还活着,以确保连接的有效性的机制。
  我们用到的很多框架都用到了心跳检测,比如服务注册到 Eureka Server 之后会维护一个心跳连接,告诉 Eureka Server 自己还活着。本文就是利用 Netty 来实现心跳检测,以及客户端重连。

二、设计思路

  1. 分为客户端和服务端
  2. 建立连接后,客户端先发送一个消息询问服务端是否可以进行通信了。
  3. 客户端收到服务端 Yes 的应答后,主动发送心跳消息,服务端接收到心跳消息后,返回心跳应答,周而复始。
  4. 心跳超时利用 Netty 的 ReadTimeOutHandler 机制,当一定周期内(默认值50s)没有读取到对方任何消息时,需要主动关闭链路。如果是客户端,重新发起连接。
  5. 为了避免出现粘/拆包问题,使用 DelimiterBasedFrameDecoder 和 StringDecoder 来处理消息。

三、编码

  1. 先编写客户端 NettyClient
public class NettyClient {

    private static final String HOST = "127.0.0.1";

    private static final int PORT = 9911;

    private ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);

    EventLoopGroup group = new NioEventLoopGroup();


    private void connect(String host,int port){
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY,true)
                    .remoteAddress(new InetSocketAddress(host,port))
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ByteBuf delimiter = Unpooled.copiedBuffer("$_", CharsetUtil.UTF_8);
                            ch.pipeline()
                                    .addLast(new DelimiterBasedFrameDecoder(1024,delimiter))
                                    .addLast(new StringDecoder())
                                    // 当一定周期内(默认50s)没有收到对方任何消息时,需要主动关闭链接
                                    .addLast("readTimeOutHandler",new ReadTimeoutHandler(50))
                                    .addLast("heartBeatHandler",new HeartBeatReqHandler());
                        }
                    });
            // 发起异步连接操作
            ChannelFuture future = b.connect().sync();
            future.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            // 所有资源释放完之后,清空资源,再次发起重连操作
            executor.execute(()->{
                try {
                    TimeUnit.SECONDS.sleep(5);
                    //发起重连操作
                    connect(NettyClient.HOST,NettyClient.PORT);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
    }

    public static void main(String[] args) {
        new NettyClient().connect(NettyClient.HOST,NettyClient.PORT);
    }

}

这里稍微复杂点的就是38行开始的重连部分。
2. 心跳消息发送类 HeartBeatReqHandler

package cn.sp.heartbeat;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * Created by 2YSP on 2019/5/23.
 */
@ChannelHandler.Sharable
public class HeartBeatReqHandler extends SimpleChannelInboundHandler<String> {

    private volatile ScheduledFuture<?> heartBeat;

    private static final String hello = "start notify with server$_";

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.writeAndFlush(Unpooled.copiedBuffer(hello.getBytes()));
        System.out.println("================");
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        if (heartBeat != null){
            heartBeat.cancel(true);
            heartBeat = null;
        }
        ctx.fireExceptionCaught(cause);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        if ("ok".equalsIgnoreCase(msg)){
            //服务端返回ok开始心跳
            heartBeat = ctx.executor().scheduleAtFixedRate(new HeartBeatTask(ctx),0,5000, TimeUnit.MILLISECONDS);
        }else {
            System.out.println("Client receive server heart beat message : --->"+msg);
        }
    }

    private class HeartBeatTask implements Runnable{

        private final ChannelHandlerContext ctx;

        public HeartBeatTask(ChannelHandlerContext ctx){
            this.ctx = ctx;
        }


        @Override
        public void run() {
            String heartBeat = "I am ok";
            System.out.println("Client send heart beat message to server: ----->"+heartBeat);
            ctx.writeAndFlush(Unpooled.copiedBuffer((heartBeat+"$_").getBytes()));
        }
    }
}

channelActive()方法在首次建立连接后向服务端问好,如果服务端返回了 “ok” 就创建一个线程每隔5秒发送一次心跳消息。如果发生了异常,就取消定时任务并将其设置为 null,等待 GC 回收。
3. 服务端 NettyServer

public class NettyServer {

    public static void main(String[] args) {
        new NettyServer().bind(9911);
    }

    private void bind(int port){
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(group)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes());

                            ch.pipeline()
                                    .addLast(new DelimiterBasedFrameDecoder(1024,delimiter))
                                    .addLast(new StringDecoder())
                                    .addLast("readTimeOutHandler",new ReadTimeoutHandler(50))
                                    .addLast("HeartBeatHandler",new HeartBeatRespHandler());
                        }
                    });
            // 绑定端口,同步等待成功
             b.bind(port).sync();
            System.out.println("Netty Server start ok ....");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
  1. 心跳响应类 HeartBeatRespHandler
package cn.sp.heartbeat;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

/**
 * Created by 2YSP on 2019/5/23.
 */
@ChannelHandler.Sharable
public class HeartBeatRespHandler extends SimpleChannelInboundHandler<String> {

    private static final String resp = "I have received successfully$_";

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        if (msg.equals("start notify with server")){
            ctx.writeAndFlush(Unpooled.copiedBuffer("ok$_".getBytes()));
        }else {
            //返回心跳应答信息
            System.out.println("Receive client heart beat message: ---->"+ msg);
            ctx.writeAndFlush(Unpooled.copiedBuffer(resp.getBytes()));
        }
    }

}

第一次告诉客户端我已经准备好了,后面打印客户端发过来的信息并告诉客户端我已经收到你的消息了。

四、测试

启动服务端再启动客户端,可以看到心跳检测正常,如下图。
服务端控制台:
在这里插入图片描述
客户端控制台:
在这里插入图片描述
现在让服务端宕机一段时间,看客户端能否重连并开始正常工作。

关闭服务端后,客户端周期性的连接失败,控制台输出如图:
在这里插入图片描述
重新启动服务端,过一会儿就会发现重连成功了。
在这里插入图片描述

五、总结

总得来说,使用 Netty 实现心跳检测还是比较简单的,这里比较懒没有使用其他序列化协议(如 ProtoBuf 等),如果感兴趣的话大家可以自己试试。
代码地址,点击这里。
有篇SpringBoot 整合长连接心跳机制的文章写的也很不错,地址https://crossoverjie.top/2018/05/24/netty/Netty(1)TCP-Heartbeat/

netty 实现长连接,心跳机制,以及重连 实现的功能 心跳机制 and 长连接 and 重连机制 and 应用消息传输: 这里最关键的就是通过netty中的 IdleStateHandler 超时机制来实现心跳和重连 然后通过org.msgpack编码器来实现跨平台数据传输, 在这实现的功能就是通过Scanner来输入消息得到服务端的回应,超过设定的超时时间就触发超时事件来进行心跳传输,如果服务端宕机客户端... 阅读详情

相关推荐

Netty-实现心跳机制-以简易手写RPC框架为例

所谓心跳机制,其本质作用就是保证服务端与客户端的连接的可用性。 当客户端出现宕机,或因网络故障无法连接工作时。服务端应该及时发现,并将该连接断开,避免服务端或重启后的客户端仍使用这个连接读写数据,造成异常。 为了实现这个功能,我们可以在客户端,一段事件没有向服务端写数据时,向服务端发送一个心跳包。服务端接收到该心跳包,则表示当前客户端仍在线。当服务端在一段事件后没有获取到来自客户端的心跳包时,则可判定客户端掉线,将与该客户端的连接断开。 Netty中为我们提供了IdleStateHandler类,我们可以用

weixin_43424751的博客 1510

Netty之心跳重连

心跳定义 心跳即在TCP长连接中,客户端和服务器之间定期发送的一种特殊的数据包,通知对方自己还在线,以确保TCP连接的有效性。为什么需要心跳 因为网络的不可靠性,有可能在TCP保持长连接的过程中,由于某些突发情况,例如网线被拔出,突然掉电等,会造成服务器和客户端的连接中断。在这些突发情况下,如果恰好服务器和客户端之间没有交互的话,那么它们是不能在短时间内发现对方已经掉线的.。为了解决这个问题,我...

大佬请赐教 514

【UE5 C++开发指南】从零配置Visual Studio 2022开发环境

本文详细指导如何从零开始为UE5 C++开发配置Visual Studio 2022环境。文章强调了VS2022与UE5的深度兼容性,并逐步讲解了社区版下载、核心工作负载(如“使用C++的游戏开发”)与组件安装、界面优化、专属工具设置以及首个C++项目的创建与验证流程,帮助开发者高效搭建专业开发环境。

weixin_29016865的博客 392

Netty——心跳机制与断线重连

在长连接模式下,为了保证系统的稳定行和可用性,心跳包和重连机制是必不可少的,让我们看看在Netty中怎么简单的实现吧

共勉 3986

【论文学习】《Fully-Convolutional Siamese Networks for Object Tracking》2016年SiamFC 全卷积孪生网络用于目标跟踪

在这项工作中,我们脱离了跟踪中采用的传统在线学习方法,并展示了一种专注于在离线阶段学习强嵌入的替代方法。与在分类设置中的使用不同,我们证明,对于跟踪应用,孪生全卷积深度网络能够更有效地使用可用数据。这不仅反映在测试时,通过执行有效的空间搜索,也反映在训练时,其中每个子窗口都有效地代表一个有用的样本,而几乎没有额外的成本。实验表明,深度嵌入为在线跟踪器提供了自然丰富的特征来源,并使简单的测试时策略表现良好。我们相信这种方法是对更复杂的在线跟踪方法的补充,并期望未来的工作能够更彻底地探索这种关系。

SkyLeopard的博客 2418

23.501中英对照(46):5QI到Qos特征的映射

注4:对于UPF终止N6与5G-AN之间的延迟,CN PDB的静态值为1毫秒,应从给定的PDB中减去该值以得出适用于无线接口的分组延迟预算。注5:对于UPF终止N6与5G-AN之间的延迟,CN PDB的静态值为2毫秒,应从给定的PDB中减去该值以得出适用于无线接口的分组延迟预算。注6:对于UPF终止N6与5G-AN之间的延迟,CN PDB的静态值为5毫秒,应从给定的PDB中减去该值以得出适用于无线接口的分组延迟预算。注:建议为任何新的非GBR资源类型的标准化5QI分配小于64的值。

51学通信的博客 1294

Netty心跳机制和客户端重连的实现

一文让你搞懂Netty心跳检测和重连

三3三的博客 3223

使用SAM进行遥感图像语义分割

SAM(Segment Anything Model)的成功表明了以数据为中心的机器学习的重要性。然而,由于遥感(RS)图像注释的困难和高成本,大量有价值的RS数据仍然没有被标记,特别是在像素级。在这项研究中,我们利用SAM和现有的RS物体检测数据集,开发了一个高效的管道来生成大规模的RS分割数据集,称为SAMRS。SAMRS在规模上超过了现有的高分辨率RS分割数据集几个数量级,并提供了物体类别、位置和实例信息,可用于语义分割、实例分割和物体检测,无论是单独还是组合。

lalula的博客 7451

一起学Netty(十四)之 Netty生产级的心跳和重连机制

sigh,这这篇博客的时候老脸还是红了一下,应该算是剽窃吧,看到别人写的代码有点无地之容,好在文章的标题是“一起学”,而不是开涛大神的“跟我学”系列的文章 最近工作比较忙,但闲暇之余还是看了阿里的冯家春(fengjiachun)的github上的开源代码Jupiter,写的RPC框架让我感叹人外有人,废话不多说,下面的代码全部截取自Jupiter,写了一个比较完整的例子,供大家一起学习分

BazingaLyncc 6万+

从CTFShow靶场实战,聊聊Node.js原型链污染漏洞的几种利用姿势(附详细复现步骤)

本文深入剖析Node.js原型链污染漏洞的原理与实战利用,通过复现CTFShow靶场题目(web338-web341),详细演示五种高级利用技巧,包括基础污染、多级污染、模板引擎RCE等,并提供防御方案与最佳实践,帮助开发者提升Web应用安全性。

weixin_30791095的博客 446

华为路由器 VRRP主备配置

3、R3 出口路由器。

一直被模仿,从未被超越 5584

java - (二)netty 心跳监测机制

1.心跳检测机制 1.1 定时断线重连 客户端断线重连机制 客户端数量多,且需要传递的数据量级较大。可以在周期性的发送数据的时候,使用。要求对数据的即时性不高的时候,才可使用。 优点:可以使用数据缓存。不是每条数据进行一次数据交互。可以定时回收资源,对资源利用率高。相对来说,即时性可以通过其他方式保证。如: 120秒自动断线。数据变化1000次请求服务器一次。300秒中自动发送不足1000次的变化数据。 对于长连接的程序断网重连几乎是程序的标配。断网重连具体可以分为两类: CONNECT失败,需要重连

saienenen的博客 1899

打破RK3588 GPIO中断响应延迟的枷锁,开启高效编程

本文针对RK3588芯片在智能安防和工业自动化应用中出现的GPIO中断响应延迟问题展开深入分析。通过硬件原理剖析,发现延迟主要源于中断控制器优先级设置、线路干扰等硬件因素,以及中断处理函数复杂、内核调度延迟等软件问题。提出硬件优化方案包括合理布局布线、电源稳定设计,软件层面则通过精准配置设备树、精简中断处理函数、利用工作队列等内核机制进行优化。测试结果显示,优化后中断响应延迟从50-80ms降至10-20ms,高负载下也能稳定在50ms以内。文章最后展望了AI技术在中断调度中的潜在应用价值。

远程部署调试 运行安装 项目调试 二次开发 项目技术新 持续迭代 部分源码免费分享 362

万字好文!Netty实现心跳机制与断线重连

点击上方 "编程技术圈"关注,星标或置顶一起成长后台回复“大礼包”有惊喜礼包!每日英文If the heart has no place to perch on, yo...

程序员小乐 450

Python爬虫教程:抓取Android或iOS应用中的数据

随着智能手机的普及,移动应用程序已经成为我们生活中不可或缺的一部分。从社交媒体、在线购物到金融服务和健康管理,几乎所有领域都有相应的手机应用程序(App)服务用户。而这些应用程序通常会存储大量的数据,例如用户行为、产品信息、订单记录等。如果我们能有效地抓取这些数据,可以为数据分析、商业智能、用户行为分析等提供有力支持。本文将重点介绍如何使用Python爬虫技术抓取Android或iOS应用中的数据,尤其是如何从这些应用的后端接口、存储、或网页中提取数据。我们将探讨如何通过反向工程技术访问移动应用中的API接

2201_76125261的博客 801

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

服务的心跳机制与断线重连,Netty底层是怎么实现的?

作者:sprinkle_lizwww.jianshu.com/p/1a28e48edd92提醒:本篇适合有一定netty基础的读者阅读心跳机制何为心跳所谓心跳, 即在 TCP 长连接中,...

Java知音 550

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

netty4 断线重连

转载:http://www.tuicool.com/articles/B7RzMbY 一 实现心跳检测 原理:当服务端每隔一段时间就会向客户端发送心跳包,客户端收到心跳包后同样也会回一个心跳包给服务端 一般情况下,客户端与服务端在指定时间内没有任何读写请求,就会认为连接是idle(空闲的)的。此时,客户端需要向服务端发送心跳消息,来维持服务端与客户端的链接。那么怎么判断客户端...

186

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

面试官问:服务的心跳机制与断线重连,Netty底层是怎么实现的?懵了

点击上方“朱小厮的博客”,选择“设为星标”后台回复"书",获取后台回复“k8s”,可领取k8s资料心跳机制何为心跳所谓心跳, 即在TCP长连接中, 客户端和服务器之间...

朱小厮的博客 794

Netty 断线重连解决方案

本篇文章是Netty专题的第七篇,前面六篇文章如下: - 高性能NIO框架Netty入门篇 - 高性能NIO框架Netty-对象传输 - 高性能NIO框架Netty-整合kryo高性能数据传输 - 高性能NIO框架Netty-整合Protobuf高性能数据传输 - Netty4自带编解码器详解 - Netty粘包拆包解决方案 用Netty实现长连接服务,当发生下面的情况时,会发生断线...

u010889990的专栏 1万+

这样讲 Netty 中的心跳机制,还有谁不会?

✋点击“肉眼品世界”,回复666 加入交流群✋“置顶公众号”,每天进步一点点基础何为心跳顾名思义, 所谓心跳, 即在 TCP 长连接中, 客户端和服务器之间定期发送的一种特殊的数据包, ...

weixin_45727359的博客 398

如何设计一个优雅的心跳机制

来源:Fate/stay night [Heaven's Feel] lost butterfly1 前言在前一篇文章《聊聊 TCP 长连接和心跳那些事》中,我们已经聊过了 TCP 中的 KeepAlive,以及在应用层设计心跳...

cqdgmow8442的博客 2135

netty-04-心跳

1.何为心跳 顾名思义, 所谓 心跳, 即在 TCP 长连接中, 客户端和服务器之间定期发送的一种特殊的数据包, 通知对方自己还在线, 以确保 TCP 连接的有效性. 为什么需要心跳 因为网络的不可靠性, 有可能在 TCP 保持长连接的过程中, 由于某些突发情况, 例如网线被拔出, 突然掉电等, 会造成服务器和客户端的连接中断. 在这些突发情况下, 如果恰好服务器和客户端之间没有交互的话, 那么它们是不能在短时间内发现对方已经掉线的. 为了解决这个问题, 我们就需要引入 心跳 机制. 心跳机制的工作原理是:

u014692224的博客 331

Netty编码解码,粘包拆包,心跳机制分析

1.Netty编码解码 ChannelPipeline相当一个管道,里面可以放各种容器,包括ChannelOutboundHandler,ChannelInboundHandler方向可以是tail->head, 也可以是head->tail,和过滤器模式一样,一级一级调用符合条件的。 字符串编码器包括:StringEncoder,StringDecoder 对象编码器包括: ObjectEncoder,ObjectDecoder 高效编码器解码器: protobuf 2.Netty

u012222011的博客 358

android 断线重连监听,安卓基于netty4.x心跳,断线重连,状态监听,数据发送

【实例简介】安卓基于netty4.x心跳,断线重连,状态监听,数据发送【实例截图】【核心代码】NaNa-Netty└── NaNa-Netty├── MyApplication.iml├── app│ ├── app.iml│ ├── build.gradle│ ├── libs│ │ └── netty-all-4.0.14.Final.jar│ ├── proguard...

weixin_39530437的博客 200
上一篇: 细说分布式锁
下一篇: 如何从零开始写一个网关
2YSP
博客等级 码龄10年 12粉丝 34原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值