netty学习笔记11 - Netty心跳检测机制

概述

我们知道在TCP长连接或者WebSocket长连接中一般我们都会使用心跳机制–即发送特殊的数据包来通告对方自己的业务还没有办完,不要关闭链接。那么心跳机制可以用来做什么呢?我们知道网络的传输是不可靠的,当我们发起一个链接请求的过程之中会发生什么事情谁都无法预料,或者断电,服务器重启,断网线之类。如果有这种情况的发生对方也无法判断你是否还在线。所以这时候我们引入心跳机制,在长链接中双方没有数据交互的时候互相发送数据(可能是空包,也可能是特殊数据),对方收到该数据之后也回复相应的数据用以确保双方都在线,这样就可以确保当前链接是有效的。

Netty的心跳机制

我们来看一下Netty的心跳机制的实现,在Netty中提供了IdleStateHandler类来进行心跳的处理,它可以对一个 Channel 的 读/写设置定时器, 当 Channel 在一定事件间隔内没有数据交互时(即处于 idle 状态), 就会触发指定的事件。


public IdleStateHandler(int readerIdleTimeSeconds, int writerIdleTimeSeconds, int allIdleTimeSeconds) {
    this((long)readerIdleTimeSeconds, (long)writerIdleTimeSeconds, (long)allIdleTimeSeconds, TimeUnit.SECONDS);

  • readerIdleTimeSeconds:设置读超时时间;
  • writerIdleTimeSeconds:设置写超时时间;
  • allIdleTimeSeconds:同时为读或写设置超时时间;

下面我们用代码实例来说明:

服务端

public class NettyServer {
    public static void main(String[] args) throws InterruptedException {
        // 创建2个线程组
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workGroup = new NioEventLoopGroup();

        // 启动程序
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workGroup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            // 往pipeline中加入一个netty提供的IdleStateHandler 提供的处理空闲状态的处理器
                            // 参数1. long readerIdleTime : 表示多长时间没有读, 就会发送一个心跳检测包检测是否连接
                            // 参数2. long writerIdleTime : 表示多长时间没有写, 就会发送一个心跳检测包检测是否连接
                            // 参数 3. long allIdleTime : 表示多长时间没有读写, 就会发送一个心跳检测包检测是否连接
                            pipeline.addLast(new IdleStateHandler(3,5,7, TimeUnit.SECONDS));
                            //加入一个对空闲检测进一步处理的handler(自定义)
                            pipeline.addLast(new NettyServerHandler());
                        }
                    });
            System.out.println("服务器准备完毕");
            ChannelFuture channelFuture = serverBootstrap.bind(7000).sync();
            channelFuture.channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }
}

服务端事件处理器

public class NettyServerHandler extends ChannelInboundHandlerAdapter {
    /**
     *
     * @param ctx 上下文
     * @param evt 事件
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if(evt instanceof IdleStateEvent) {
            //将  evt 向下转型 IdleStateEvent
            IdleStateEvent event = (IdleStateEvent) evt;
            String eventType = null;
            switch (event.state()) {
                case READER_IDLE:
                    eventType = "读空闲";
                    break;
                case WRITER_IDLE:
                    eventType = "写空闲";
                    break;
                case ALL_IDLE:
                    eventType = "读写空闲";
                    break;
            }
            System.out.println(ctx.channel().remoteAddress() + "--超时时间--" + eventType);
            System.out.println("服务器做相应处理..");

            //如果发生空闲,我们关闭通道
            // ctx.channel().close();
        }
    }
}

如服务端事件处理器
假如一个通道没有在3秒读数据,或者5秒类写数据,发生了读空闲或者写空闲,或者读写空闲,那么就会触发userEventTriggered方法,并触发相对应的事件,我们可以做出相对于的处理,这就是Netty的心跳机制,

发布了83 篇原创文章 · 获赞 3 · 访问量 9839

猜你喜欢

转载自blog.csdn.net/fyj13925475957/article/details/104371459