【图解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.mfbz.cn/a/696228.html

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

相关文章

免费!GPT-4o发布,实时语音视频丝滑交互

We’re announcing GPT-4o, our new flagship model that can reason across audio, vision, and text in real time. 5月14日凌晨&#xff0c;OpenAI召开了春季发布会&#xff0c;发布会上公布了新一代旗舰型生成式人工智能大模型【GPT-4o】&#xff0c;并表示该模型对所有免费…

AI智能体做高考志愿填报分析

关注公众号&#xff0c;赠送AI/Python/Linux资料&#xff0c;对AI智能体有兴趣的朋友也可以添加一起交流 高考正在进行时&#xff0c;学生焦虑考试&#xff0c;家长们焦虑的则是高考志愿怎么填。毕竟一个好的学校&#xff0c;好的专业是进入社会的第一个敲门砖 你看张雪峰老师…

Tomcat源码解析(八):一个请求的执行流程(附Tomcat整体总结)

Tomcat源码系列文章 Tomcat源码解析(一)&#xff1a;Tomcat整体架构 Tomcat源码解析(二)&#xff1a;Bootstrap和Catalina Tomcat源码解析(三)&#xff1a;LifeCycle生命周期管理 Tomcat源码解析(四)&#xff1a;StandardServer和StandardService Tomcat源码解析(五)&…

Python opencv读取深度图,网格化显示深度

效果图&#xff1a; 代码&#xff1a; import cv2 import osimg_path "./outdir/180m_norm_depth.png" depth_img cv2.imread(img_path, cv2.IMREAD_ANYDEPTH) filename os.path.basename(img_path) img_hig, img_wid depth_img.shape # (1080, 1920) print(de…

设计模式- 责任链模式(行为型)

责任链模式 责任链模式是一种行为模式&#xff0c;它为请求创建一个接收者对象的链&#xff0c;解耦了请求的发送者和接收者。责任链模式将多个处理器串联起来形成一条处理请求的链。 图解 角色 抽象处理者&#xff1a; 一个处理请求的接口&#xff0c;可以通过设置返回值的方…

Python基础教程(八):迭代器与生成器编程

&#x1f49d;&#x1f49d;&#x1f49d;首先&#xff0c;欢迎各位来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里不仅可以有所收获&#xff0c;同时也能感受到一份轻松欢乐的氛围&#xff0c;祝你生活愉快&#xff01; &#x1f49d;&#x1f49…

Buildroot和Debian文件系统修改方法

本文档主要介绍在没有编译环境的情况下&#xff0c;如何修改buildroot和debian文件系统方法&#xff0c;如在buildroot文件系统中添加文件、修改目录等文件操作&#xff0c;在debian文件系统中&#xff0c;安装软件库、工具、扩大文件系统空间等等操作。 1.Debian文件系统 …

【Python从入门到进阶】57、Pandas入门:背景、应用场景与基本操作

一、引言 1、Pandas简介 在数字化时代&#xff0c;数据已经成为企业决策和个人洞察的重要基础。无论是金融市场的波动、零售业的销售趋势&#xff0c;还是科研实验的结果&#xff0c;都蕴含在大量的数据之中。然而&#xff0c;如何有效地提取、分析和解读这些数据&#xff0c…

嵌入式应用之FIFO模块原理与实现

FIFO介绍与原理 FIFO是First-In First-Out的缩写&#xff0c;它是一个具有先入先出特点的缓冲区。FIFO在嵌入式应用的非常广泛&#xff0c;可以说有数据收发的地方&#xff0c;基本就有FIFO的存在。或者为了降低CPU负担&#xff0c;提高数据处理效率&#xff0c;可以在积累到一…

2、数据操作

索引从0开始 一行 [1,:] 一列[:,1] 子区域&#xff1a;[1:3,1:] 第一行和第二行&#xff0c;从第一列开始 [::3,::2] 每3行一跳&#xff0c;每2列一跳 torch.tensor([[1,2,3,4]] 按位置算 xy ,x-y x*y x**y&#xff08;幂&#xff09; 1、广播机制形状不一样&#xff0c;…

一个简单好用的 C# Easing Animation 缓动动画类库

文章目录 1.类库说明2.使用步骤2.1 创建一个Windows Form 项目2.2 安装类库2.3 编码2.4 效果 3. 扩展方法3.1 MoveTo 动画3.2 使用回调函数的Color动画3.3 属性动画3.4 自定义缓动函数 4.该库支持的内置缓动函数5.代码下载 1.类库说明 App.Animations 类库是一个很精炼、好用的…

C-MAPSS数据集探索性分析

实验数据为商用模块化航空推进系统仿真C-MAPSS数据集&#xff0c;该数据集为NASA格林中心为2008年第一届预测与健康管理国际会议(PHM08)竞赛提供的引擎性能退化模拟数据集&#xff0c;数据集整体信息如下所示&#xff1a; 涡扇发动机仿真模拟模型如下图所示。 仿真建模主要针对…

【前端】使用window.print() 前端实现网页打印详细教程(含代码示例)

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主。 &#x1f913; 同时欢迎大家关注其他专栏&#xff0c;我将分享Web前后端开发、人工智能、机器学习、深…

Vuex3学习笔记

文章目录 1&#xff0c;入门案例辅助函数 2&#xff0c;mutations传参辅助函数 3&#xff0c;actions辅助函数 4&#xff0c;getters辅助函数 5&#xff0c;模块拆分6&#xff0c;访问子模块的state辅助函数 7&#xff0c;访问子模块的getters辅助函数 8&#xff0c;访问子模块…

Java--递归

1.递归就是A方法调用A方法&#xff0c;也就是调用自己本身 2.利用递归可以用简单的程序来解决一些复杂的问题&#xff0c;它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解&#xff0c;递归策略只需少量的程序就可描述出解题过程所需要的多次重复…

【MySQL数据库】:MySQL索引特性

目录 索引的概念 磁盘 磁盘的基本特征 MySQL与磁盘交互的基本单位 索引的理解 建立测试表 理解单个Page 理解多个Page 页目录 单页情况 多页情况 索引的数据结构 聚簇索引 VS 非聚簇索引 索引操作 创建主键索引 创建唯一索引 创建普通索引 创建全文索引 查询…

Nginx服务配置

一、Nginx服务的主配置文件nginx.conf vim /usr/local/nginx/conf/nginx.conf 全局块&#xff1a;全局配置&#xff0c;对全局生效&#xff1b;events块&#xff1a;配置影响 Nginx 服务器与用户的网络连接&#xff1b;http块&#xff1a;配置代理&#xff0c;缓存&#xff0c…

重温共射放大电路

1、放大概念 小功率信号变成一个大功率信号&#xff0c;需要一个核心器件做这件事&#xff0c;核心器件的能量由电源提供&#xff0c;通过核心器件用小功率的信号去控制大电源&#xff0c;来实现能量的转换和控制&#xff0c;前提是不能失真&#xff0c;可以用一系列正弦波进行…

conda 创建环境失败

conda create -n pylableimg python3.10在conda &#xff08;base&#xff09;环境下&#xff0c;创建新的环境&#xff0c;失败。 报错&#xff1a; LookupError: didn’t find info-scipy-1.11.3-py310h309d312_0 component in C:\Users\Jane.conda\pkgs\scipy-1.11.3-py310h…

RK3568-修改fiq-debugger调试串口

瑞芯微SDK默认将uart2_m0作为调试串口,以下方法将调试串口修改为uart5_m1。修改bootloader 修改/OK3568-linux-source/rkbin/tools/ddrbin_param.txt文件,5表示串口5。1表示复用m1。执行./ddrbin_tool ddrbin_param.txt ../bin/rk35/rk3568_ddr_1560MHz_v1.11.bin命令修改ub…