IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Netty功能实现:实现心跳检测 -> 正文阅读

[Java知识库]Netty功能实现:实现心跳检测

netty实现心跳检测

检测逻辑:

1) 服务端启动,客户端建立连接,连接的目的是互相发送消息。
2) 如果客户端在工作,服务端一定能收到数据,如果客户端空闲,服务端会出现资源浪费。
3) 服务端需要一种检测机制,验证客户端的活跃状态,不活跃则关闭。

需求设计:

1) 客户端向服务端发送 “I am alive” , sleep一个随机时间,模拟空闲状态
2) 服务端收到消息后,返回“over”, 客户端有空闲,记录空闲次数
3) 设定阈值,达到阈值时主动关闭连接

在这里插入图片描述

服务端编写

public class HreatBeatServer {
    public static void main(String[] args) {

        //创建两个Reactor 构建主从 Reactor 模型
        //用于处理 连接和读写事件 , 无限循环组(线程池)
        //管理 channel 监听事件
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        //    我们需要一个服务端引导程序来开启服务端。
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        //将主从 Reactor 入参,设置当前参数
        //这个方法返回的事对象本身,我们可以点出其他方法, 这种返回类型为对象自身 提供了 链式编程的方式
        serverBootstrap.group(bossGroup, workerGroup)
                //我们需要设置 channel 的 类型
                //对应的是   netty                NIO                    BIO
                //NioServerSocketChannel  <== ServerSocketChannel <== ServerSocket
                .channel(NioServerSocketChannel.class)
                //设置当前通道的处理器,使用Netty提供的日志打印处理器
                .handler(new LoggingHandler(LogLevel.INFO))
                //定义客户端连接处理的使用
                //此方法需要设置参数  ChannelInitializer 通道初始化器
                //初始化 要处理客户端 通道, 所以泛型设置为 SocketChannel
                //此类 为抽象类 需要实现其抽象方法 initchannel (alt+enter)快捷键
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        //通过channel 获取管道 pipeline
                        //    通道代表我们连接的角色, 管道代表处理业务得逻辑管理
                        // 管道相当于 链表,可以将不同的处理器连接起来,管理处理器的顺序
                        // 使用时 常常使用的事尾插法, addList 将加入到尾部
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        pipeline.addLast(new StringDecoder());
                        pipeline.addLast(new StringEncoder());
                        /*
                         * 使用心跳检测处理器
                         * 读空闲 写空闲 读写空闲 的超时时间
                         * 最后一个参数是 时间的单位
                         * IdleStateHandler发现有空闲的时候 会触发 IdleStateEvent时间
                         * 他会把事件推送给下一个 handler的指定方法 userEventTriggered 去处理
                         * */
                        pipeline.addLast(new IdleStateHandler(5, 10, 20, TimeUnit.SECONDS));

                        socketChannel.pipeline().addLast(new HreatBeatServerHandler());
                    }
                });
        System.out.println("服务端初始化完成");
        //    设置并启动端口号,但需要使用sync 异步启动
        try {
            ChannelFuture future = serverBootstrap.bind(2020).sync();
            //    将关闭通道的方式也设置为异步的
            //    阻塞Finally中的代码执行
            future.channel().closeFuture().sync();

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //   优雅方式都关闭
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }

    }
}

IdleStateHandler , 是netty提供的处理器

1)超过多长时间没有读 readerIdleTime
2) 超过多长时间没有写 writerIdleTime
3) 超过多长时间没有读和写 allIdleTime

底层实现检测的是 IdleStateEvent事件,通过管道传递给下一个handler处理,处理方法是userEventTriggered。

处理器编写

public class HreatBeatServerHandler extends SimpleChannelInboundHandler<String> {
    private int times;

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        if ("I am alive".equals(msg)) {
            ctx.writeAndFlush(Unpooled.copiedBuffer("over", CharsetUtil.UTF_8));
        }
    }

    //处理心跳检测事件的方法
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        IdleStateEvent event = (IdleStateEvent) evt;
        String eventDesc = null;
        switch (event.state()) {
            case READER_IDLE:
                eventDesc = "读空闲";
                break;
            case WRITER_IDLE:
                eventDesc = "写空闲";
                break;
            case ALL_IDLE:
                eventDesc = "读写空闲";
                break;
        }
        System.out.println(ctx.channel().remoteAddress() + "发生超时事件--" + eventDesc);
        times++;
        if (times > 3) {
            System.out.println("空闲次数超过三次 关闭连接");
            ctx.writeAndFlush("you are out");
            ctx.channel().close();
        }
        //super.userEventTriggered(ctx, evt);

    }
}

其中IdleStateEvent事件,分为READER_IDLE、WRITER_IDLE、ALL_IDLE三大类

客户端编写

客户端不断循环给服务端发消息确认存活的期间 线程睡眠 模拟失去心跳场景

package com.hyc.netty.Hreatbeat;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import java.util.Random;

public class HreatbeatClient {
    public static void main(String[] args) {
        //客户端只需要一个事件循环组
        EventLoopGroup group = new NioEventLoopGroup();
        //    客户端启动的对象
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        ChannelPipeline pipeline = socketChannel.pipeline();
                        pipeline.addLast(new StringDecoder());
                        pipeline.addLast(new StringEncoder());
                        socketChannel.pipeline().addLast(new HreatbeatClientHandler());
                    }
                });
        System.out.println("客户端初始化完成");
        try {
            ChannelFuture future = bootstrap.connect("127.0.0.1", 2020).sync();
            String data = "I am alive";
            while (future.channel().isActive()) {
                //模拟空闲状态
                int num = new Random().nextInt(10);
                Thread.sleep(num * 1000);
                future.channel().writeAndFlush(data);
            }
            //future.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            group.shutdownGracefully();
        }

    }

    static class HreatbeatClientHandler extends SimpleChannelInboundHandler<String> {

        @Override
        protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
            System.out.println("server data:" + s);
            if ("you are out".equals(s)) {
                System.out.println("关闭");
                channelHandlerContext.channel().close();
            }

        }
    }
}

客户端随机线程睡眠 一旦接受到 服务端返回的you are out代表空闲次数超过了 3次 则关闭客户端连接

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-12-01 17:34:35  更:2021-12-01 17:35:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:26:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码