【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

AIDD-人工智能药物设计-构建基于机器学习方法的在线预测平台高准确预测药物诱导骨毒性

在此基础上,提取多种药物分子特征,包括分子指纹(如MACCS、Morgan、RDKit、TopologicalTorsion、AtomPairs与Descriptors)及分子图谱,通过Transformer编码器与神经网络进行机器学习模型训练。最后,将训练好的模型部署为在线Web服务器(BoneToxPD),供用户快速预测药物的骨毒性。本研究不仅在骨毒性预测的准确性方面取得了突破,还在模型解释性方面提供了新的视角,通过注意力机制精准识别出影响骨毒性的关键化学基团,推动药物研发领域更安全、更高效的发展。

itwangyang520的博客 1079

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

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

共勉 3986

Windows 64 位系统下安装配置 DOSBox 及 debug.exe

该篇博客同样作为类似问题 “如何在 Windows 64 位系统下进入 debug” 的答案。 很多同学初看王爽的《汇编语言》,或者因为其它原因需要进入 debug 调试模式下学习汇编语言的时候,会发现进入不了,出现类似以下的错误提示。 这是因为他们使用的是 64 位的 Windows 系统(Win 7,Win 8 以及 Win 10 等),而 64 位 Windows 系统不再支持在命令提示符窗口下进入 debug 调试模式。那么对于使用 64 位 Windows 系统的用户来说,该怎样才能够顺利进入 d

加号减减号的博客 5万+

Autosar开发实战:DaVinci Configurator Pro新建工程保姆级教程(附目录结构解析)

本文详细介绍了使用DaVinci Configurator Pro创建Autosar工程的完整流程,包括环境准备、工程配置、目录结构解析及常见问题排查。通过实战演示和深度解读,帮助开发者快速掌握工具使用技巧,优化工程管理,提升开发效率。特别适合需要理解Autosar开发中DaVinci Config工具链的工程师。

weixin_30872157的博客 456

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

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

三3三的博客 3223

Halcon实战:5分钟搞定金属表面划痕检测(附完整代码解析)

本文提供了一份基于Halcon的金属表面划痕检测实战指南。通过核心的动态阈值算法,快速从图像中提取局部对比度异常区域,并结合形态学后处理与特征筛选,精准识别划痕。文章详解了从代码搭建、参数优化到工业场景适配的全流程,帮助工程师在五分钟内构建稳定高效的机器视觉检测方案。

weixin_29084231的博客 495

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

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

BazingaLyncc 6万+

Dify框架面试内容整理-如何优化Dify的应用性能?

为1536维)可选用 PCA、FAISS 的量化压缩方法降低维度(如128、256、512);对知识库预览、任务流配置等页面,使用 nginx/cache-control 减少请求。API 响应耗时(P50/P95)、Token 使用量、缓存命中率、向量检索耗时;对 Prompt+输入内容计算 Hash,缓存相同请求的返回结果;使用占位符 + 函数拼接,按需组合 Prompt,而非静态长模板;数据量大时,应在构建索引前清洗冗余段落、统一格式,避免重复向量。维度越低,检索越快,但可能影响召回准确度,需平衡。

不务正业的猿 1549

【系统架构设计师】2025年下半年真题论文回忆版及写作要点

本文摘要围绕云原生数据库、性能测试、无服务器架构和秒杀场景等关键技术进行论述。云原生数据库通过容器化、微服务和自动化运维实现弹性扩展;性能测试需要规划测试场景并关注响应时间等关键指标;无服务器架构以事件驱动为核心,简化开发流程;秒杀场景需组合运用扩容、缓存、限流等技术应对高并发。这些技术方案为构建现代高可用系统提供了重要参考。

数据知道的博客 6156

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

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

saienenen的博客 1899

一台NAS两个系统:飞牛nas上完美运行群晖DSM?(飞牛nas+群晖nas套娃安装实操)

想在飞牛NAS上体验群晖DSM系统?💡 本文详细记录了飞牛nas上部署群晖的完整过程,从镜像转换到系统安装,每一步都有详细说明 🖥️,让你在不增加硬件成本的情况下,轻松实现一套硬件、多种系统的灵活部署 ✅

XiaoqiangClub的博客 2370

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

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

程序员小乐 450

双目深度相机--10.双目视觉的主要步骤讲解分析

双目视觉技术通过模拟人眼原理,利用两个相机从不同视角采集图像,实现三维坐标计算。其核心流程包括:1)系统标定,消除相机畸变并建立坐标映射关系;2)图像同步采集与预处理;3)立体匹配,寻找左右图像对应点;4)基于视差图的深度计算;5)三维重建生成点云或网格模型;6)结果应用如目标测距、三维建模等。关键技术难点在于精确标定和准确匹配,这两步直接影响最终深度计算的精度。该技术广泛应用于自动驾驶、工业检测、VR等领域,实现了从二维图像到三维空间的精准转换。

AIoT深度探索者 | 嵌入式系统架构师 深耕物联网(IoT)与人工智能(AI)融合技术,聚焦​​边缘计算、图像开发、低功耗通信协议​​,致力于智能硬件,关注我获取最新技术文章信息与海量资源~ 625

IDEA的使用指南

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

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

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

Java知音 550

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

netty4 断线重连

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

186

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

面试官问:服务的心跳机制与断线重连,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、付费专栏及课程。

余额充值