【图解IO与Netty系列】Netty核心组件解析

Netty核心组件解析

  • Bootstrap & ServerBootstrap
  • EventLoop & EventLoopGroup
  • Channel
  • ChannelHandler & ChannelPipeline & ChannelHandlerContext
    • ChannelHandler
    • ChannelPipeline
    • ChannelHandlerContext
  • ChannelFuture

Bootstrap & ServerBootstrap

Bootstrap和ServerBootstrap是Netty应用程序的启动引导器,通过它可以配置我们的Netty应用程序并启动。其中Bootstrap是Netty客户端使用的启动引导器,而ServerBootstrap则是Netty服务端使用的启动引导器。

EventLoop & EventLoopGroup

EventLoop是事件循环,也是就我们在NIO程序中while循环调用Selector的select()方法进行监听然后处理就绪事件的逻辑,现在Netty通过EventLoop封装事件循环,使得我们无需重复编写事件循环的代码,只需要专注于就绪事件的处理逻辑。

每个EventLoop都对应一个线程,每个EventLoop又属于某个EventLoopGroup,因此EventLoopGroup相当于是线程组。我们常用的是NioEventLoopGroup,NioEventLoopGroup内部包含了一个或多个NioEventLoop,由我们的参数进行设置。

在这里插入图片描述

一个NioEventLoop内部包含一个Selector和一个Queue<Runnable>类型的taskQueue。

在这里插入图片描述

Selector就是NIO中的Selector,Selector是一个多路复用器,我们可以往Selector注册多个Channel,Selector可以帮我们监听注册在其上的Channel,当我们调用Selector的select()方法时,当前线程就阻塞,通过Selector监听注册在其上的Channel,等待关注的事件就绪。

在这里插入图片描述

于是,NioEventLoop内部线程的事件循环,就通过Selector的select()方法监听注册到Selector上的Channel,等待一个或多个Channel有关注的事件就绪。

当有事件就绪时,NioEventLoop内部线程会调用processSelectedKeys()方法处理就绪事件对应的Channel。

当processSelectedKeys()方法调用完毕后,NioEventLoop还会调用runAllTasks()方法处理被提交到自己的taskQueue中的异步任务。一些比较耗时但是实时性不高的任务,我们可以把它提交到NioEventLoop的taskQueue中让它异步处理。

当taskQueue中的任务处理完,一个事件循环就结束,进入下一次循环。

在这里插入图片描述

Channel

这里的Channel和NIO的Channel不是同一个东西,这里的Channel是Netty对NIO的Channel经过封装后的属于Netty自己的Channel。比如NIO中的ServerSocketChannel和SocketChannel,Netty把它们封装成了NioServerSocketChannel和NioSocketChannel。

在这里插入图片描述

除了持有NIO的Channel以外,还保存了各自关注的事件类型,等真正把NIO的Channel注册到Selector上的时候,就可以直接设置对应的事件类型。NioServerSocketChannel保存的是连接就绪事件OP_ACCEPT,而NioSocketChannel保存的是读就绪事件OP_READ。

在这里插入图片描述

在使用Java原生的NIO时,我们都会设置Channel为非阻塞的,也就是调用configureBlocking(false)方法,这里Netty自动帮我们设置为非阻塞了,无需我们手动设置。比如NioServerSocketChannel在构造方法中就调用了ServerSocketChannel的configureBlocking(false)方法。

在这里插入图片描述

除了NioServerSocketChannel和NioSocketChannel以外,Netty还有其他类型的Channel,比如BIO类型的Channel、UDP协议的Channel,这里就不列举了。

然后Netty中的每个Channel,都有对应ChannelPipeline用来处理Channel中就绪的事件。

在这里插入图片描述

ChannelHandler & ChannelPipeline & ChannelHandlerContext

与Chandler相关的其他组件包括ChannelHandler、ChannelPipeline、ChannelHandlerContext。每个Chandler都会有一个ChandlerPipeline与之对应,用于处理该Chandler上发生的事件,而ChandlerPipeline又会通过它内部的ChandlerHandler去处理到来的事件。

ChannelHandler

ChannelHandler是专门用于处理就绪事件的,我们在开发Netty应用程序时,主要就是编写各种ChannelHandler,在ChannelHandler中各种事件触发的方法中实现自己的处理逻辑。

ChannelHandler又分为是处理入站事件还是出站事件的。所谓入站事件,就是由于接收到外部的数据或消息等而触发的事件就是入站事件,比如读就绪事件就是入站事件,因为有数据到达才会触发读就绪事件;而出站事件则与入站事件相反,由自己主动触发的,流动方向是向外的事件就是出站事件,比如写就绪事件。

在这里插入图片描述

如果要编写处理入站事件的ChannelHandler,我们可以实现ChannelInboundHandler接口,ChannelInboundHandler就是专门用于处理入站事件的;如果要编写处理出站事件的ChannelHandler,我们可以实现ChannelOutboundHandler接口,ChannelOutboundHandler就是专门用于处理出站事件的。

在这里插入图片描述

ChannelInboundHandler和ChannelOutboundHandler都继承了ChannelHandler接口。

在这里插入图片描述

但是ChannelInboundHandler和ChannelOutboundHandler有许多不同类型事件对应的方法,如果直接实现ChannelInboundHandler或ChannelOutboundHandler,我们要一一编写每个方法的实现逻辑。但是我们可能不会全部事件都关注,可能只会关注一两种类型的事件。

于是我们可以通过继承Netty提供的适配器类来实现我们的ChannelHandler,我们就可以选择性的实现我们关注的事件类型对应的方法。Netty提供的适配器类就是ChannelInboundHandlerAdapter和ChannelOutboundHandlerAdapter,ChannelInboundHandlerAdapter是用于处理入站事件的适配器类,ChannelOutboundHandlerAdapter是用于处理出站事件的适配器类。

在这里插入图片描述

ChannelInboundHandlerAdapter实现了ChannelInboundHandler接口,而ChannelOutboundHandlerAdapter则实现了ChannelOutboundHandler接口。

在这里插入图片描述

ChannelPipeline

在Netty中,每个Channel对应一个ChannelPipeline。在Channel初始化的时候,就会为Channel创建一个对应的ChannelPipeline。ChannelPipeline是一个由多个ChannelHandler组成的双向链表,ChannelPipeline中有固定的head(头部Handler)和tail(尾部Handler)。

在这里插入图片描述

ChannelPipeline中除head和tail以外的ChannelHandler可以通过ChannelInitializer进行安装,一开始ChannelPipeline中除head和tail以外,中间只有一个ChannelInitializer。当Channel(NIO的Channel)被注册到Selector中时,会触发ChannelInitializer的调用,安装指定的ChannelHandler到Pipeline中,并把自己从链表中删除。

在这里插入图片描述

ChannelPipeline中对应就绪事件的处理,就是调用ChannelPipeline中的ChannelHandler与就绪事件匹配的方法。如果是入栈事件,则会以从head到tail的方向逐一调用负责处理入站事件的ChannelHandler来处理;如果是出站事件,则会以tail到head的方向逐一调用负责处理出站事件的ChannelHandler来处理。

在这里插入图片描述

ChannelHandlerContext

其实ChannelPipeline中的双向链表并不是由ChannelHandler直接组成的双向链表,而是在ChannelHandler外头再包了一层ChannelHandlerContext,因为ChannelHandler本身并没有维护组成双向链表需要的前后指针,ChannelHandlerContext才维护了这个前后指针,也就是说ChannelPipeline里头是由ChannelHandlerContext组成的双向链表。

在这里插入图片描述

之所以要在ChannelHandler之上再包一层ChannelHandlerContext来组成链表,是出于单一职责的考虑。首先ChannelHandler是用来处理事件的,那么ChannelHandler就应该只关注事件的处理,让它去维护前后指针就不太合适。就像LinkedList一样,我们放进去的元素,也不是直接组成双向链表的,LinkedList里头也是会包一个Node,再由Node的前后指针组成双向链表。

以下是ChannelHandlerContext的一些常用方法:
在这里插入图片描述

其中fireXxx是ChannelHandlerContext定义的以fire开头的一些方法,这些方法都是用于触发ChannelHandler中不同类型的事件处理方法,一旦调用这些方法,就会从当前ChannelHandlerContext开始沿着责任链调用每个ChannelHandler对应的事件的处理方法。比如调用了当前ChannelHandlerContext的fireChannelRead(Object msg)方法,就会从当前ChandlerHandlerContext对应的ChandlerHandler开始,沿着责任链顺序调用每个ChandlerHandler的channelRead(…)方法。

在这里插入图片描述

ChannelFuture

Netty中的操作都是异步操作,比如我们通过Bootstrap的connect(String inetHost, int inetPort)连接服务器、通过ServerBootstrap的bind(int inetPort)监听某个端口等,这些都是异步操作。这些异步操作都会返回一个ChannelFuture,我们可以通过ChannelFuture的addListener(…)方法添加一个ChannelFutureListener,等Netty的异步操作完成后,会触发添加到ChannelFuture的ChannelFutureListener进行相应的处理。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

A股所有公司ZL申请与创新绩效分析(2000-2022年)

数据简介&#xff1a;专利是创新成果的主要载体&#xff0c;专利所包含的技术、经济、法律等信息主要通过结构化专利专利文献著录项的形式加以呈现。专利申请与创新绩效已成为衡量上市公司竞争力的重要指标。目前&#xff0c;各国ZSCQ管理部门开发管理的开放式平台是获取ZL数据…

OBS 录屏软件:录制圆形头像画中画,设置卡通人像(保姆级教程,有步骤图,建议收藏)

Mac分享吧 文章目录 一、OBS录屏软件 圆形头像画中画效果注意&#xff1a;圆形画中画仅需要在软件中设置一次&#xff0c;每次录制&#xff0c;使用带有圆形头像画中画的场景 录制视频即可。该场景不可删除&#xff01;&#xff01;&#xff01;若删除&#xff0c;则需要重新设…

时序数据库是Niche Market吗?

引言 DB-Engines的流行程度排行从其评估标准[4]可以看出完全不能够做为市场规模的评估标准。甚至于在知道市场规模后可以用这个排行作为一个避雷手册。毕竟现存市场小&#xff0c;可预见增长规模小&#xff0c;竞争大&#xff0c;创新不足&#xff0c;那只能卷价格&#xff0c…

数据结构---查找

个人介绍 hello hello~ &#xff0c;这里是 code袁~&#x1f496;&#x1f496; &#xff0c;欢迎大家点赞&#x1f973;&#x1f973;关注&#x1f4a5;&#x1f4a5;收藏&#x1f339;&#x1f339;&#x1f339; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的…

运 算 符

算术运算符 算术运算符包括&#xff1a;&#xff0c;-&#xff0c;*&#xff0c;/&#xff0c;%&#xff0c;&#xff0c;-- 当左右两边都是数值型时&#xff0c;则做加法运算。 当左右两边有一方为字符串&#xff0c;则做拼接运算。任何一个 Java 对象都可以转换为字符串。 …

.Net实现SCrypt Hash加密

方案1 &#xff08;加密后存储“算法设置”、“盐(随机值)”、“Hash值”&#xff0c;以“$”分隔&#xff09;&#xff1a; //Nuget引入SCrypt.NET库 using Org.BouncyCastle.Crypto.Generators; using Scrypt; using System; using System.Security.Cryptography; namespace …

8.让画面动起来

一、Unity Shader中的内置变量&#xff08;时间篇&#xff09; 动画效果往往都是把时间添加到一些变量的计算中&#xff0c;以便在时间变化的同时也可以随之变化。Unity shader提供了一系列关于时间的内置变量来允许我们方便地在Shader中访问运行时间&#xff0c;实现各种动画…

暴雨推出X705显示器:23.8英寸100Hz IPS屏

IT资讯 6月 7 日消息&#xff0c;日前&#xff0c;暴雨发布了一款 23.8 英寸 IPS 显示器&#xff0c;直屏、支持 100Hz 刷新率。 据官方介绍&#xff0c;X705 显示器分辨率为 19201080&#xff0c;亮度为 300 尼特&#xff08;典型值&#xff09;&#xff0c;对比度 1000:1&…

从Log4j和Fastjson RCE漏洞认识jndi注入

文章目录 前言JNDI注入基础介绍靶场搭建漏洞验证注入工具 log4j RCE漏洞分析漏洞靶场检测工具补丁绕过 Fastjson RCE漏洞分析漏洞靶场检测工具补丁绕过 总结 前言 接着前文的学习《Java反序列化漏洞与URLDNS利用链分析》&#xff0c;想了解为什么 Fastjson 反序列化漏洞的利用…

关于用宽带(拨号)连接VPN无法上网,但是wifi或者热点就可以的问题

参考链接&#xff1a;https://zhuanlan.zhihu.com/p/580929250https://zhuanlan.zhihu.com/p/580929250 https://blog.csdn.net/Yaoyao2024/article/details/132245249文章浏览阅读10w次&#xff0c;点赞161次&#xff0c;收藏515次。很多同学在学习访问学校提供的资源时或者一…

队列和栈的实现

文章目录 队列队列的定义队列常见的基本操作队列的顺序存储结构实现 栈栈的定义栈的常见基本操作栈的顺序存储实现 栈的链式存储实现 队列 队列的定义 队列&#xff08;queue&#xff09;是只允许在一端进行插入操作&#xff0c;而在另一端进行删除操作的线性表。队列是一种先…

Vitis HLS 学习笔记--聚合与解聚-AXI主接口

目录 1. 简介 2. 用法及语法 3. 详细解读 4. 总结 1. 简介 在使用 Vitis HLS 工具进行硬件设计时&#xff0c;如果你在接口上使用了结构体&#xff0c;工具会自动把结构体里的所有元素组合成一个整体。就像把一堆零件组装成一个玩具一样。这样做的好处是&#xff0c;数据可…

【西瓜书】大题

1.线性回归 思路&#xff1a;ywxb&#xff0c;w为一维数组&#xff0c;求均方误差MSE&#xff0c;对w和b分别求偏导为0得到关于w和b的闭式求解。预测第十年的代入ywxb求解即可。 2.查准率、查全率 思路&#xff1a;先计算每个算法测试结果的混淆矩阵&#xff0c;再根据混淆矩阵…

pyrouge(ROUGE-1.5.5)的安装步骤和使用说明(适用于Linux 系统)

摘要&#xff1a;本文讲解了如何配置和使用文本摘要的评价指标ROUGE(linux 系统)。 ✅ NLP 研 1 选手的学习笔记 简介&#xff1a;小王&#xff0c;NPU&#xff0c;2023级&#xff0c;计算机技术 研究方向&#xff1a;摘要生成、大语言模型生成 文章目录 一、为啥要写这篇博客&…

问题汇总:MPU6050(软件iic)

以下为个人问题汇总&#xff0c;排查点汇总可能大有缺陷&#xff0c;如有错误&#xff0c;欢迎指正。 排查点汇总 检查软件iic的时序操作用示波器或逻辑分析仪检查波形 无法使用逻辑分析仪进行I/O引脚波形分析 充当SDA、SCL的引脚要配置为推挽输出; 另外&#xff0c;逻辑分…

挑战绝对不可能:再证有长度不同的射线

黄小宁 一空间坐标系中有公共汽车A&#xff0c;A中各座位到司机处的距离h是随着座位的不同而不同的变数&#xff0c;例如5号座位到司机处的距离是h3&#xff0c;…h5&#xff0c;…。A移动了一段距离变为汽车B≌A&#xff0c;B中5号座位到司机处的距离h’h3&#xff0c;…h’h5…

LLVM Cpu0 新后端 系列课程总结

想好好熟悉一下llvm开发一个新后端都要干什么&#xff0c;于是参考了老师的系列文章&#xff1a; LLVM 后端实践笔记 代码在这里&#xff08;还没来得及准备&#xff0c;先用网盘暂存一下&#xff09;&#xff1a; 链接: https://pan.baidu.com/s/1yLAtXs9XwtyEzYSlDCSlqw?…

测试与开发

目录 按照测试目标分类 界面测试 功能测试 性能测试 可靠性测试 安全性测试 易用性测试 按照执行方式分类&#xff1a; 测试方法 白盒测试 语句覆盖 条件覆盖 判定条件覆盖 条件组合覆盖 路径覆盖 黑盒测试 灰盒测试 按照测试阶段分类 单元测试 集成测试 …

【iOS】界面推出的方法

【iOS】界面推出的方法 在学习过程中我们发现在iOS中有两种界面推出的方法&#xff1a;push 和 present这两种方法都可以用来推出一个新的界面 但是这两者是存在区别的 push 方法是通过 UINavigationController 进行导航,新的视图控制器会被压入导航栈中&#xff0c;可以跨级…

写给大数据开发,如何去掌握数据分析

这篇文章源于自己一个大数据开发&#xff0c;天天要做分析的事情&#xff0c;发现数据分析实在高大上很多&#xff0c;写代码和做汇报可真比不了。。。。 文章目录 1. 引言2. 数据分析的重要性2.1 技能对比2.2 业务理解的差距 3. 提升数据分析能力的方向4. 数据分析的系统过程4…