Netty 组件介绍 - EventLoop

 

概要

  • 把  channel 理解为数据的通道
  • 把 msg 理解为流动的数据,最开始输入是 ByteBuf,但经过pipeline 的加工,会变成其它类型对象,最后输出又变成 ByteBuf
  • 把 handler 理解为数据的处理工序

工序有多道,合在一起就是 pipeline,pipeline 负责发布事件(读、读取完成..) 传播给每个handler,handler对自己感兴趣的事件进行处理(重写了相应事件处理方法)。

handler分inbound 和 Outbound 两类。

  • 把 eventLoop 理解为处理数据的工人

工人可以管理多个 channel 的 io 操作,并且一旦工人负责了某个 channel,就要负责到底(绑定)。

工人既可以执行 io 操作,也可以进行任务处理,每位工人有任务队列,队列里可以堆放多个channel 的待处理任务,任务分为普通任务、定时任务。

工人按照 pipeline 顺序依次按照 handler的规划(代码)处理数据,可以为每道工序指定不同的工人。

EventLoop

EventLoop本质是一个单线程执行器(同时维护了一个selector),一个EventLoopGroup是一组EventLoop,channel调用EventLoopGroup的register方法绑定一个EventLoop,后续这个channel的IO事件,都由此EventLoop来处理。

  • 一个EventLoopGroup 包含一个或多个EventLoop
  • 一个EventLoop只和一个Thread绑定。
  • 所有EventLoop的io事件只和绑定的Thread上处理
  • 一个channel只注册给一个EventLoop
  • 一个EventLoop可能注册一个或多个channel

普通任务&定时任务

public class EventLoop {
    private static final Logger logger = LoggerFactory.getLogger(EventLoop.class);
    public static void main(String[] args) {

        //1、创建时事件环组
        NioEventLoopGroup group = new NioEventLoopGroup(2); //io事件、普通任务、定时任务
        //DefaultEventLoop group = new DefaultEventLoop(); //普通任务、定时任务

        //2、获取下一个事件循环对象

        io.netty.channel.EventLoop next = group.next();

        //3、执行普通任务
        group.next().submit(()->{
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            logger.info("执行普通任务");
        });

        //4、执行定时任务

        group.next().scheduleAtFixedRate(()->{
            logger.info("执行定时任务");
        },0,1, TimeUnit.SECONDS);

        logger.info("main~");

    }

}

控制台

IO任务

Server

public class IoEventLoopServer {
    private static final Logger logger = LoggerFactory.getLogger(IoEventLoopServer.class);

    public static void main(String[] args) {
        new ServerBootstrap()
                .group(new NioEventLoopGroup())
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                            @Override
                            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                ByteBuf buf = (ByteBuf) msg;
                                logger.info(buf.toString(Charset.defaultCharset()));
                            }
                        });

                    }
                })
                .bind(8080);
    }
}

client

public class IoEventLoopClient {
    private static final Logger logger = LoggerFactory.getLogger(EventLoop.class);

    public static void main(String[] args) throws InterruptedException {

        Channel channel = new Bootstrap()
                .group(new NioEventLoopGroup())
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new StringEncoder());
                    }
                })
                .connect(new InetSocketAddress("127.0.0.1", 8080))
                .sync()
                .channel();
        System.out.println(channel);
    }
}

在channel处多次进行数据发送(server使用同一线程进行接收处理)。

验证可知:一个EventLoop只和一个Thread绑定,后续这个channel的IO事件,都由此EventLoop来处理。

分工细化

在上述server代码做调整,将NioEventLoopGoup职责细化(设置两个worker线程)。

启动三个client向server发送信息,发现一个EventLoop可能注册一个或多个channel。

public class IoEventLoopServer {
    private static final Logger logger = LoggerFactory.getLogger(IoEventLoopServer.class);

    public static void main(String[] args) {
        new ServerBootstrap()
                //.group(new NioEventLoopGroup())
                //boss只负责ServerSocketChannel上的accept  worker只负责ServerChannel的读写
                .group(new NioEventLoopGroup(),new NioEventLoopGroup(2))
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new ChannelInboundHandlerAdapter() {
                            @Override
                            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                ByteBuf buf = (ByteBuf) msg;
                                logger.info(buf.toString(Charset.defaultCharset()));
                            }
                        });

                    }
                })
                .bind(8080);
    }
}

进一步细化

场景:已知一个EventLoop可以绑定多个channel,假设某个EventLoop绑定了1000个channel,其中有一个channel要进行大规模的逻辑处理耗费时间长,势必会影响后续channel的处理。

方案:将耗时的channel事件绑定额外的EventLoopGroup组。

改进后Server代码

public class IoEventLoopServer {
    private static final Logger logger = LoggerFactory.getLogger(IoEventLoopServer.class);

    public static void main(String[] args) {

        //创建一个独立的EventLoopGroup
        DefaultEventLoopGroup group = new DefaultEventLoopGroup();
        new ServerBootstrap()
                //.group(new NioEventLoopGroup())
                //boss只负责ServerSocketChannel上的accept  worker只负责ServerChannel的读写
                .group(new NioEventLoopGroup(),new NioEventLoopGroup(2))
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {
                        ch.pipeline().addLast("handle1",new ChannelInboundHandlerAdapter() {
                            @Override
                            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                ByteBuf buf = (ByteBuf) msg;
                                logger.info(buf.toString(Charset.defaultCharset()));
                                ctx.fireChannelRead(msg);//将消息传递给下一个handler
                            }
                        }).addLast(group,"handle2",new ChannelInboundHandlerAdapter() {
                            @Override
                            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                ByteBuf buf = (ByteBuf) msg;
                                logger.info(buf.toString(Charset.defaultCharset()));
                            }
                        });

                    }
                })
                .bind(8080);
    }
}

控制台输出

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/907128.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

oracle 对应的JDBC驱动 版本

下载网址&#xff1a;JDBC and UCP Downloads page

整理 【 DBeaver 数据库管理工具 】的一些基础使用

目录 连接设置切换工作空间SQL编辑器&#xff08;写sql语句&#xff09;打开方式新建查询&#xff08;sql编辑器&#xff09;打开写的 sql 查询&#xff08;项目浏览器&#xff09; 备份sql文件查看历史执行语句自动保存sql语句的文件&#xff08;编辑器&#xff09;关闭自动生…

(九)JavaWeb后端开发——Servlet

目录 1.Servlet由来 2.Servlet快速入门 3.Servlet执行原理 4.Servlet生命周期 1.Servlet由来 在JaveEE API文档中对Servlet的描述是&#xff1a;可以运行在服务器端的微小程序&#xff0c;但是实际上&#xff0c;Servlet就是一个接口&#xff0c;定义了Java类被浏览器访问…

LLC Power Switches and Resonant Tank 笔记

1.概述 上面是一个典型的LLC电路。注意Lm是励磁电感&#xff0c;就是次级线圈空载时的主变压器电感&#xff0c;据说在计算谐振频率时无需关心。然后&#xff0c;作为DCDC电源&#xff0c;它通过调整谐振频率&#xff0c;来改变输出的电流。负载越大&#xff0c;频率越低&#…

项目模块十三:Util模块

一、项目设计思路 用于之后协议使用的工具类 二、静态成员函数 1、分割函数 static size_t Split(const string &src, const string &sep, vector<string> *array) string.find(const string &str, size_t pos 0) string.substr(size_t pos 0, size_t…

Chrome与夸克谁更节省系统资源

在当今数字化时代&#xff0c;浏览器已经成为我们日常生活中不可或缺的一部分。无论是工作、学习还是娱乐&#xff0c;我们都依赖于浏览器来访问互联网。然而&#xff0c;不同的浏览器在性能和资源消耗方面存在差异。本文将探讨Chrome和夸克两款浏览器在系统资源消耗方面的表现…

Qt第三课 ----------输入类的控件属性

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

后端:Spring、Spring Boot-实例化Bean依赖注入(DI)

文章目录 1. 实例化Bean2. 使用FactoryBean3. 依赖注入(DI)3.1 AutoWired 属性注入(查找顺序&#xff1a;先类型&#xff0c;后名字)3.2 AutoWired 在构造函数&参数上的使用3.3 Inject和Resource 进行依赖注入3.4 Value 进行注入 1. 实例化Bean 默认使用无参构造函数&…

qt QPicture详解

1、概述 QPicture类是Qt框架中的一个重要图形类&#xff0c;它主要用于记录和回放QPainter的绘图指令。这个类能够跨平台、无分辨率依赖地绘制图形&#xff0c;非常适合用于实现打印预览和图像操作等场景。QPicture可以将绘图操作序列化为一种独立于平台的格式&#xff0c;保存…

【计算机网络教程】课程 章节测试1 计算机网络概述

一. 单选题&#xff08;共16题&#xff09; 1 【单选题】以下关于TCP/IP参考模型缺点的描述中&#xff0c;错误的是&#xff08; &#xff09;。 A、在服务、接口与协议的区别上不很清楚 B、网络接口层本身并不是实际的一层 C、它不能区分数据链路和物理层 D、传输层对…

金融标准体系

目录 基本原则 标准体系结构图 标准明细表 金融标准体系下载地址 基本原则 需求引领、顶层设计。 坚持目标导向、问题导向、结果 导向有机统一&#xff0c;构建支撑适用、体系完善、科学合理的金融 标准体系。 全面系统、重点突出。 以金融业运用有效、保护有力、 管理高…

Linux练习作业

1.搭建dns服务器能够对自定义的正向或者反向域完成数据解析查询。 2.配置从DNS服务器&#xff0c;对主dns服务器进行数据备份 环境准备 主从服务器都需要进行的操作#关闭防火墙、SELinnux systemctl stop firewalld setenforce 0#软件安装 yum install bind -y实验一&#…

【STL_list 模拟】——打造属于自己的高效链表容器

一、list节点 ​ list是一个双向循环带头的链表&#xff0c;所以链表节点结构如下&#xff1a; template<class T>struct ListNode{T val;ListNode* next;ListNode* prve;ListNode(int x){val x;next prve this;}};二、list迭代器 2.1、list迭代器与vector迭代器区别…

《Qwen2-VL》论文精读【上】:发表于2024年10月 Qwen2-VL 迅速崛起 | 性能与GPT-4o和Claude3.5相当

1、论文地址Qwen2-VL: Enhancing Vision-Language Model’s Perception of the World at Any Resolution 2、Qwen2-VL的Github仓库地址 该论文发表于2024年4月&#xff0c;是Qwen2-VL的续作&#xff0c;截止2024年11月&#xff0c;引用数24 文章目录 1 论文摘要2 引言3 实验3.…

LiveQing视频点播流媒体RTMP推流服务功能-支持电子放大拉框放大直播视频拉框放大录像视频流拉框放大电子放大

LiveQing视频点播流媒体RTMP推流服务功能-支持电子放大拉框放大直播视频拉框放大录像视频流拉框放大电子放大 1、鉴权直播2、视频点播3、RTMP推流视频直播和点播流媒体服务 1、鉴权直播 云直播服务-》鉴权直播 -》播放 &#xff0c;左键单击可以拉取矩形框&#xff0c;放大选中…

Zypher Research:服务器抽象叙事,GameFi 赛道的下一个热点?

继链抽象、账户抽象的概念后&#xff0c;Zypher Network 进一步提出了服务器抽象的概念&#xff0c;并基于 zk 技术率先推出了应用于 Web3 游戏领域的服务器抽象方案。基于该方案&#xff0c;游戏开发者能够在完全去中心化的环境下创建、运行游戏&#xff0c;而不需要依赖传统的…

【SpringCloud详细教程】-01-一文了解微服务

精品专题&#xff1a; 01.《C语言从不挂科到高绩点》课程详细笔记 https://blog.csdn.net/yueyehuguang/category_12753294.html?spm1001.2014.3001.5482 02. 《SpringBoot详细教程》课程详细笔记 https://blog.csdn.net/yueyehuguang/category_12789841.html?spm1001.20…

在使用 AMD GPU 的 PyTorch 中实现自动混合精度

Automatic mixed precision in PyTorch using AMD GPUs — ROCm Blogs 随着模型规模的增加&#xff0c;训练它们所需的时间和内存——以及因此而产生的成本——也在增加。因此&#xff0c;采取任何措施来减少训练时间和内存使用都是非常有益的。这就是自动混合精度&#xff08;…

基于布局的3D场景生成技术:SceneCraft

1. 概述 随着室内设计和虚拟现实技术的快速发展,快速生成高质量的3D室内场景成为行业需求的重要方向。SceneCraft是一种新型的3D场景生成技术,旨在根据用户提供的布局和文本描述,一键生成详细的室内3D场景。该技术不仅简化了设计流程,还大大提高了设计效率和用户体验。 2…

【Python爬虫实战】深入解析 Selenium:从元素定位到节点交互的完整自动化指南

#1024程序员节&#xff5c;征文# &#x1f308;个人主页&#xff1a;易辰君-CSDN博客 &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html ​ 前言 Selenium 是进行网页自动化操作的强大工具&#xff0c;在测试、数据抓取、用户行…