Netty实战应用学习笔记-中级拓展篇(八)

「深入浅出Netty」不愧是阿里架构师,这篇Netty实战文档太实用 前言 什么是Netty? Netty是由JBOSS提供的一个java开源框架。 Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。也就是说,Netty是一个基于NIO的客户,服务器端编程框架,使用Netty可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户,服务端应用。 作为当前最流行的NIO框架,Netty在互联... 阅读详情

💓 项目八:心跳服务与断线重连

项目概述

项目名称:itstack-demo-netty-2-08
核心功能:实现心跳检测和断线自动重连机制
技术要点:IdleStateHandler、ChannelFutureListener、EventLoop调度

为什么需要这个项目?

实际问题:

  • 长连接可能因网络波动、服务器重启等原因断开
  • 无法及时发现连接已断开(半开连接)
  • 连接断开后需要手动重连,用户体验差
  • 需要保持连接存活,避免被防火墙关闭

解决方案:

  • ✅ IdleStateHandler:自动检测空闲状态
  • ✅ 心跳检测:定期发送心跳包,保持连接存活
  • ✅ 自动重连:连接断开后自动重新连接
  • ✅ 指数退避:避免频繁重连,保护服务器

适用场景:

  • IM即时通讯(保持长连接,像微信一样)
  • 物联网设备(设备与服务器保持心跳)
  • 游戏服务器(玩家连接保活)
  • 分布式系统(服务间心跳检测)

核心问题

为什么需要心跳和重连?

在实际应用中,网络连接可能因为各种原因断开(网络波动、服务器重启、超时等),需要:

  1. 心跳检测:定期检测连接是否存活
  2. 断线重连:连接断开后自动重新连接

核心知识点

1. 心跳检测机制(IdleStateHandler)

什么是IdleStateHandler?

Netty提供的空闲状态检测处理器,可以检测读空闲、写空闲、读写空闲。

Pipeline配置(服务端)

public class MyChannelInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel channel) {
        // 心跳监测:2秒内没有读/写操作触发事件
        channel.pipeline().addLast(new IdleStateHandler(2, 2, 2));
        
        // 其他处理器
        channel.pipeline().addLast(new LineBasedFrameDecoder(1024));
        channel.pipeline().addLast(new StringDecoder(Charset.forName("GBK")));
        channel.pipeline().addLast(new StringEncoder(Charset.forName("GBK")));
        channel.pipeline().addLast(new MyServerHandler());
    }
}

IdleStateHandler参数说明:

new IdleStateHandler(
    2,  // readerIdleTimeSeconds:2秒内没有读取到数据触发READER_IDLE
    2,  // writerIdleTimeSeconds:2秒内没有写入数据触发WRITER_IDLE
    2   // allIdleTimeSeconds:2秒内没有读写操作触发ALL_IDLE
);

工作原理:

时间轴:
0s -----> 2s -----> 4s -----> 6s
|         |         |         |
连接建立   读空闲     读空闲     读空闲
          触发事件   触发事件   触发事件
2. 处理心跳事件

MyServerHandler.java

@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
    if (evt instanceof IdleStateEvent) {
        IdleStateEvent e = (IdleStateEvent) evt;
        
        if (e.state() == IdleState.READER_IDLE) {
            // 读空闲:客户端2秒没发数据,可能掉线了
            System.out.println("Reader Idle - 客户端可能掉线");
            ctx.writeAndFlush("客户端你在吗?\r\n");
            ctx.close();  // 关闭连接,触发客户端重连
            
        } else if (e.state() == IdleState.WRITER_IDLE) {
            // 写空闲:服务端2秒没发数据,发送心跳包
            ctx.writeAndFlush("心跳包\r\n");
            
        } else if (e.state() == IdleState.ALL_IDLE) {
            // 读写都空闲
            ctx.writeAndFlush("全部空闲检测\r\n");
        }
    }
}

三种空闲状态:

状态触发条件应用场景
READER_IDLEN秒内没有读取到数据检测客户端是否掉线
WRITER_IDLEN秒内没有写入数据主动发送心跳包
ALL_IDLEN秒内没有读写操作综合检测
3. 断线重连机制

场景1:连接失败时重连(ChannelFutureListener)

// NettyClient.java
public void connect(String inetHost, int inetPort) {
    EventLoopGroup workerGroup = new NioEventLoopGroup();
    try {
        Bootstrap b = new Bootstrap();
        b.group(workerGroup);
        b.channel(NioSocketChannel.class);
        b.option(ChannelOption.AUTO_READ, true);
        b.handler(new MyChannelInitializer());
        
        ChannelFuture f = b.connect(inetHost, inetPort).sync();
        f.addListener(new MyChannelFutureListener());  // 添加监听器
        f.channel().closeFuture().sync();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } finally {
        workerGroup.shutdownGracefully();
    }
}

MyChannelFutureListener.java

public class MyChannelFutureListener implements ChannelFutureListener {
    @Override
    public void operationComplete(ChannelFuture channelFuture) {
        if (channelFuture.isSuccess()) {
            System.out.println("连接成功");
            return;
        }
        
        // 连接失败,延迟1秒后重连
        final EventLoop loop = channelFuture.channel().eventLoop();
        loop.schedule(new Runnable() {
            @Override
            public void run() {
                try {
                    new NettyClient().connect("127.0.0.1", 7397);
                    Thread.sleep(500);
                } catch (Exception e) {
                    System.out.println("重连失败,继续尝试...");
                }
            }
        }, 1L, TimeUnit.SECONDS);  // 延迟1秒执行
    }
}

场景2:连接断开时重连(channelInactive)

// MyClientHandler.java
@Override
public void channelInactive(ChannelHandlerContext ctx) {
    System.out.println("断开链接,开始重连:" + ctx.channel().localAddress());
    
    // 启动新线程进行重连
    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                new NettyClient().connect("127.0.0.1", 7397);
                System.out.println("重连成功");
                Thread.sleep(500);
            } catch (Exception e) {
                System.out.println("重连失败,继续尝试...");
            }
        }
    }).start();
}
4. 完整心跳重连流程
【正常心跳流程】
客户端                    服务端
  |                        |
  |----连接建立------------>|
  |<---"连接成功"-----------|
  |                        |
  |  (2秒内无数据)          |
  |                        |--检测到READER_IDLE
  |<---"客户端你在吗"-------|
  |                        |--ctx.close()
  |                        |
  |--检测到channelInactive--|
  |                        |
  |--启动重连线程---------->|
  |----重新连接------------>|
  |<---"连接成功"-----------|

【连接失败重连流程】
客户端                    服务端
  |                        |
  |----尝试连接------------>X (服务端未启动)
  |                        
  |--连接失败
  |--触发MyChannelFutureListener
  |--延迟1秒
  |----重新尝试连接-------->X
  |--继续重试...

项目总结

核心技术:

  • ✅ IdleStateHandler:自动检测空闲状态
  • ✅ userEventTriggered:处理空闲事件
  • ✅ ChannelFutureListener:监听连接结果
  • ✅ EventLoop.schedule:延迟重连

适用场景:

  • IM即时通讯(保持长连接)
  • 物联网设备(设备与服务器保持心跳)
  • 游戏服务器(玩家连接保活)
  • 分布式系统(服务间心跳检测)

注意事项:

  • ⚠️ 每次重连都创建新的EventLoopGroup会导致资源泄漏
  • ⚠️ 建议实现指数退避策略(1s, 2s, 4s, 8s…)
  • ⚠️ 生产环境心跳间隔建议30秒以上

改进建议:

// 1. 复用EventLoopGroup
private static EventLoopGroup workerGroup = new NioEventLoopGroup();

// 2. 指数退避重连
int retryCount = 0;
long delay = Math.min(1 << retryCount, 60);  // 最大60秒
loop.schedule(reconnectTask, delay, TimeUnit.SECONDS);
retryCount++;

bugstack虫洞栈 | netty4.1案例文章列表汇总,跟着案例学Netty itstack-demo-netty netty4.x案例 微信公众号:bugstack虫洞栈,欢迎您的关注&获取更多案例与源码!博客栈:https://bugstack.cn 本专题针对netty4.x分为从;基础入门篇(九篇)、中级拓展篇(八篇)、高级应用篇(三章),由浅入深实现netty服务功能,介绍netty如何从上手到实战。 基础入门篇(九篇) netty案例,netty4.1... 阅读详情

相关推荐

netty案例,netty4.1中级拓展篇八《Netty心跳服务与断线重连》

前言介绍 在我们使用netty中,需要监测服务是否稳定以及在网络异常链接断开时候可以自动重连。需要实现监听;f.addListener(new MyChannelFutureListener()) 环境准备 1、jdk1.8【jdk1.7以下只能部分支持netty】 2、Netty4.1.36.Final【netty3.x 4.x 5每次的变化较大,接口类名也随着变化】 代码示例 itstack-...

bugstack虫洞栈 2069

Netty实战应用学习笔记-中级拓展篇(一)

Netty实战应用学习笔记-中级拓展篇

java_rutu的博客 1072

netty案例,netty4.1中级拓展篇一《Netty与SpringBoot整合》

前言介绍 在实际的开发中,我们需要对netty服务进行更多的操作,包括;获取它的状态信息、启动/停止、对客户端用户强制下线等等,为此我们需要把netty服务加入到web系统中,那么本章节介绍如何将Netty与SpringBoot整合。 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使...

bugstack虫洞栈 2642

Netty实战应用学习笔记-中级拓展篇(六)

Netty实战应用学习笔记-中级拓展篇

java_rutu的博客 630

netty案例,netty4.1中级拓展篇五《基于Netty搭建WebSocket,模仿微信聊天页面》

前言介绍 本章节我们模仿微信聊天页面,开发一个基于Netty搭建WebSocket通信案例。Netty的应用方面非常广;聊天、MQ、RPC、数据等等,在5G到来的时候更加需要大量数据传输,Netty的应用也会更加广阔。 1、这个案例使用SpringBoot+Netty+WebSocket搭建功能。 2、使用Netty提供的HttpServerCodec、HttpObjectAggregator、...

bugstack虫洞栈 3072

netty案例,netty4.1中级拓展篇七《Netty请求响应同步通信》

前言介绍 在我们实现开发RPC框架的时候,需要选择socket的通信方式。而我们知道一般情况下socket通信类似与qq聊天,发过去消息,什么时候回复都可以。但是我们RPC框架通信,从感觉上类似http调用,需要在一定时间内返回,否则就会发生超时断开。这里我们选择netty作为我们的socket框架,采用future方式进行通信。 Dubbo:国内最早开源的 RPC 框架,由阿里巴巴公司开发并于...

bugstack虫洞栈 2265

Netty实战应用学习笔记-中级拓展篇(十二)

Netty实战应用学习笔记-中级拓展篇

java_rutu的博客 1087

netty案例,netty4.1中级拓展篇三《Netty传输Java对象》

前言介绍 Netty在实际应用级开发中,有时候某些特定场景下会需要使用Java对象类型进行传输,但是如果使用Java本身序列化进行传输,那么对性能的损耗比较大。为此我们需要借助protostuff-core的工具包将对象以二进制形式传输并做编码解码处理。与直接使用protobuf二进制传输方式不同,这里不需要定义proto文件,而是需要实现对象类型编码解码器,用以传输自定义Java对象。 pro...

bugstack虫洞栈 2142

Netty实战应用学习笔记-中级拓展篇(九)

Netty实战应用学习笔记-中级拓展篇

java_rutu的博客 1063

netty案例,netty4.1中级拓展篇十二《Netty流量整形数据流速率控制分析与实战》

作者:付政委 | 关注微信公众号:bugstack虫洞栈,获取专题案例源码 前言介绍 你是否使用过某盘,在前几年我们使用的时候速度飞快,上传下载嗖嗖嗖。但是近年来只要不办会员,速度慢的像蜗牛,当然人家也得赚钱我们能理解。那么这样的限速是怎么实现的呢,我们这个案例使用Netty的流量整形进行限速传输,测试过程中当你把流量整形功能去掉后你就是年费VIP。 流量整形(Traffic Shaping...

bugstack虫洞栈 3696

netty案例,netty4.1中级拓展篇二《Netty使用Protobuf传输数据》

前言介绍 在netty数据传输过程中可以有很多选择,比如;字符串、json、xml、java对象,但为了保证传输的数据具备;良好的通用性、方便的操作性和传输的高性能,我们可以选择protobuf作为我们的数据传输格式。目前protobuf可以支持;C++、C#、Dart、Go、Java、Python等,也可以在JS里使用。知识点;ProtobufDecoder、ProtobufEncoder、Pr...

bugstack虫洞栈 2080

Netty实战应用学习笔记-中级拓展篇(十三)

Netty实战应用学习笔记-中级拓展篇

java_rutu的博客 570

netty案例,netty4.1中级拓展篇四《Netty传输文件、分片发送、断点续传》

前言介绍 1、在实际应用中我们经常使用到网盘服务,他们可以高效的上传下载较大文件。那么这些高性能文件传输服务,都需要实现的分片发送、断点续传功能。 2、在Java文件操作中有RandomAccessFile类,他可以支持文件的定位读取和写入,这样就满足了我们对文件分片的最基础需求。 3、Netty服务端启动后,可以向客户端发送文件传输指令;允许接收文件、控制读取位点、记录传输标记、文件接收完成。 ...

bugstack虫洞栈 3229

Netty实战应用学习笔记-中级拓展篇(五)

Netty实战应用学习笔记-中级拓展篇

java_rutu的博客 636

EPSON RX8010SJ RTC实战:I2C寄存器配置避坑指南(附完整初始化代码)

本文详细解析了EPSON RX8010SJ RTC芯片在I2C寄存器配置中的常见问题与解决方案,包括TEST位、STOP位和中断控制等关键配置要点。通过实战经验分享和完整的初始化代码模板,帮助开发者避免常见陷阱,确保RTC模块的稳定运行。

weixin_28678831的博客 407

SAP ERP销售应收&成本科目确定

ERP作为业财一体软件,其中最核心的就是业务与财务模块的自动集成,无需财务进行手工做账,提高工作效率的同时降低人工操作产生的误差。今天浅浅的分享一下SD模块生成会计凭证时,借贷项确定的系统配置。一般项目上借贷项、科目都有FICO提供,但是具体的集成配置是在SD这边。

weixin_43657667的博客 1569

Netty实战应用学习笔记-中级拓展篇(七)

Netty实战应用学习笔记-中级拓展篇

java_rutu的博客 322

【Unity游戏开发】SDK接入与集成——小白入门篇

一、简介   通常一款游戏开发到后期,一般都会涉及到第三方SDK的接入与集成,对于不熟悉SDK接入的同学来说,接SDK每次都是云里雾里,而熟悉SDK接入的同学又觉得不断地重复做接入SDK工作这样没有成就感,太尼玛无聊了(Android渠道一弄就十几个,直接吐血)。其实通常情况下接入SDK都是很简单的一个过程,本系列博客就让马三和大家从小白开始,从零基础开始学习如何接入SDK以及一些常见的SDK的...

weixin_34195142的博客 5763

Netty实战应用学习笔记-中级拓展篇(三)

Netty实战应用学习笔记-中级拓展篇

java_rutu的博客 306

ROS入门(一)——ROS安装(vmware16+ubuntu20.04+ROS-Noetic)

嵌套:ROS可以在Ubuntu上运行,Ubuntu在虚拟机Vmware中安装。 从 虚拟机vmware安装→ubuntu安装→ros安装,逐步介绍安装ROS环境的过程。整个过程是我一步步跟着各种博客安装实现的,亲测可行。 版本: Vmware :Vmware Workstation16 Ubuntu :20.04 ROS :Noetic 其中vmware直接载当前最新版本就好,而ubuntu的版本要注意一下。 在ROS官网(cn - ROS Wiki),我们进入到ROS安装的步骤界面,可以看..

Netceor的博客 9742

RT-Thread littefs控制GD32F4xx片内Flash

GD32F4xx RT-Thread下使用littefs 控制片内flash 调试记录

madao1234的博客 995

Netty实战应用学习笔记-中级拓展篇(二)

Netty实战应用学习笔记-中级拓展篇

java_rutu的博客 301

2021年03月 C/C++(五级)真题解析#中国电子学会#全国青少年软件编程等级考试

给定一个十进制正整数n(0 < n < 1000000000),每个数位上数字均不为0。n的位数为m。现在从m位中删除k位(0

人生就是一个不断学习的过程 1012
上一篇: Netty实战应用学习笔记-中级拓展篇(七)
下一篇: Netty实战应用学习笔记-中级拓展篇(九)
不早睡不改名@
博客等级 码龄5年 536粉丝 306原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值