当前位置:首页 > Web开发 > 正文

netty 实现心跳检查

2024-03-31 Web开发

标签:

一.心跳介绍

  网络中的接收和发送数据都是使用操作系统中的SOCKET进行实现。但是如果此套接字已经断开,那发送数据和接收数据的时候就一定会有问题。

1.心跳机制:

  是服务端和客户端定时的发送一个心跳包(自定义的数据结构体),让对方知道自己还活着,处于在线状态,以确保连接真实有效的一种机制。

2.心跳检查:

  心跳检查是查看服务端和客户端是否定时的在正常的发送心跳包。

  java的定时线程任务中,我们也可以去实现定时的一些轮询任务,但是netty给我们提供了一些自身封装实现好的一些心跳检查机制,我们可以利用netty来实现高效的心跳检查机制。

二.netty 提供的心跳

  netty4.x中为我们提供了IdleStateHandler来检查服务端和客户端的心跳。

IdleStateHandler 类中是这样描述的:
triggers an {@link IdleStateEvent} when a {@link Channel} has not performed read, write, or both operation for a while. 解释:在一段时间内,如果有读、写、读写空闲时发生时,会触发这个这个事件 IdleStateHandler会记录IdleStateEvent事件(读空闲、写空闲、读写空闲)交给下一个handler处理 IdleStateHandler(long readerIdleTime, long writerIdleTime, long allIdleTime,TimeUnit unit) 参数说明: 1. long readerIdleTime : 表示多长时间没有读, 就会发送一个心跳检测包检测是否连接 2. long writerIdleTime : 表示多长时间没有写, 就会发送一个心跳检测包检测是否连接 3. long allIdleTime : 表示多长时间没有读写, 就会发送一个心跳检测包检测是否连接 4.TimeUnit unit:时间大小

三.自定义心跳实现

下面我们利用nettyIdleStateHandler来实现一个断开重连的心跳检查机制

1.心跳实现思路:

服务端: 服务端正常配置启动,并利用IdleStateHandler中的IdleStateEvent事件,在发生5秒后没有读事件发生时,就会触发userEventTrigger事件,如果服务端在5秒内没有发生读的事件,说明客户端已经断开。 服务端正常编写,只不过是多了一个IdleStateHandler事件处理的handler而已。 客户端: 客户端需要考虑2件事,第1是怎么定时的去向服务端发送数据,第2是如果失败时怎样去尝试再次连接。好在netty的handler都已提供了相应的处理机制和方法。 1.定时发送数据问题: 客户端利用IdleStateHandler的事件特性在发生IdleStateEvent后,会记录下触发的事件,然后交给下一下handler处理,我们可以通过ChannelInboundHandlerAdapter的userEventTriggered方法来向服务端写数据,也就是说如果4秒内没有发生写事件,就会触发userEventTrigger方法,我们可以在该方法中向服务端写数据。 2.重连问题: 当服务端发生异常断开时,我们可以利用ChannelInboundHandlerAdapter的channelInactive方法进行重连。在这里需要注意,由于netty每次进行重连时会使用的Bootstrap是不共享的,因此需要通过设置@Sharable标签让bootstrap数据共享,这样当每次尝试重连时就可以把之前设置的一些绑定信息可以共享使用。

2 .UML类图

技术图片

技术图片

3.实现代码: 3.1 服务端代码实现

服务端代码实现没什么难度,一共是3个类组成:

: 服务端绑定启动项参数配置      
: 服务端创建时加载netty的channelhandler
: 服务端创建时加载自定义的channelhandler  3.2客户端代码实现

 客户端代码稍微复杂一点,但其本质上和普通的客户端都一样

          : 客户端绑定启动项参数配置
: 客户端心跳事件发生时触发此类中的方法
      : 客户端断开连接后,尝试重连的自定义handler,该类是个抽象类,需要在调用时传入相应的参数,具体情况在该类上有解释
        : 客户端在尝试重连时,需要透传的参数

HeartBeatServer

package com.zpb.netty.heartbeat.server; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; /** * @Desc: com.zpb.netty.heare1 * @Date: 2019/11/30 * @Auther: pengbo.zhao * @version: 1.0 */ public class HeartBeatServer { private int port; public HeartBeatServer(int port) { this.port = port; } public void start(){ EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap serverBootstrap = new ServerBootstrap().group(bossGroup, workerGroup); serverBootstrap.channel(NioServerSocketChannel.class); serverBootstrap.handler(new LoggingHandler(LogLevel.INFO)); serverBootstrap.option(ChannelOption.SO_BACKLOG, 128); serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true); serverBootstrap.childHandler(new ServerInitHandler()); ChannelFuture channelFuture = serverBootstrap.bind(port).sync(); System.out.println("Server start listen at... " + port); channelFuture.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); }finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) { new HeartBeatServer(8888).start(); } }

HeartBeatServerInitHandler

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/web/41950.html