200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > 五 Netty核心组件

五 Netty核心组件

时间:2021-05-27 14:30:29

相关推荐

五 Netty核心组件

为了后期更好地理解和进一步深入 Netty,有必要总体认识一下 Netty 所用到的核心组件以及他们在整个 Netty 架构中是如何协调工作的。

一、Netty 有如下几个核心组件

Bootstrap & ServerBootstrap:客户端和服务端的引导类Channel:代表了一个链接,与EventLoop一起用来参与IO处理。ChannelFuture:Netty 为异步非阻塞,即所有的 I/O 操作都为异步的,因此,我们不能立刻得知消息是否已经被处理了。Netty 提供了 ChannelFuture 接口,通过该接口的 addListener() 方法注册一个 ChannelFutureListener,当操作执行成功或者失败时,监听就会自动触发返回结果。EventLoop & EventLoopGroup:Channel处理IO操作,一个EventLoop可以为多个Channel服务。而一个EventLoopGroup会包含多个EventLoop。ChannelHandler:为了支持各种协议和处理数据的方式,便诞生了Handler组件。Handler主要用来处理各种事件,这里的事件很广泛,比如可以是连接、数据接收、异常、数据转换等。ChannelPipeline:提供了 ChannelHandler 链的容器,并定义了用于在该链上传播入站

和出站事件流的 API。

核心组件的高层类图如下:

核心类之间的数量关系

二、Bootstrap & ServerBootstrap

这 2 个类都继承了AbstractBootstrap,因此它们有很多相同的方法和职责。它们都是启动器,能够帮助 Netty 使用者更加方便地组装和配置 Netty ,也可以更方便地启动 Netty 应用程序。相比使用者自己从头去将 Netty 的各部分组装起来要方便得多,降低了使用者的学习和使用成本。它们是我们使用 Netty 的入口和最重要的 API ,可以通过它来连接到一个主机和端口上,也可以通过它来绑定到一个本地的端口上。总的来说,它们两者之间相同之处要大于不同。

Bootstrap & ServerBootstrap对于Netty就相当于 Spring Boot 是 Spring 的启动器。

它们和其它组件之间的关系是它们将 Netty 的其它组件进行组装和配置,所以它们会组合和直接或间接依赖其它的类。

Bootstrap 用于启动一个 Netty TCP 客户端,或者 UDP 的一端。通常使用 #connet(...) 方法连接到远程的主机和端口,作为一个 Netty TCP 客户端。也可以通过 #bind(...) 方法绑定本地的一个端口,作为 UDP 的一端。仅仅需要使用一个 EventLoopGroup 。

ServerBootstrap 往往是用于启动一个 Netty 服务端。通常使用 #bind(...) 方法绑定本地的端口上,然后等待客户端的连接。使用两个 EventLoopGroup 对象( 当然这个对象可以引用同一个对象 ):第一个用于处理它本地 Socket 连接的 IO事件处理,而第二个责负责处理远程客户端的 IO 事件处理。

三、Channel

Netty网络通信的组件,用于网络IO操作。通过Channel可以获得当前王略连接的通道的状态与网络配置参数。Channel提供异步的网络IO操作,调用后立即返回ChannelFuture,通过注册监听,或者同步等待,最终获取结果。

Channel根据不同的协议、不同的阻塞类型,分为不同的Channel类型,通过名称也能大概猜出来其分别的作用:

Channel 是 Netty 网络操作抽象类,它除了包括基本的 I/O 操作,如 bind、connect、read、write 之外,还包括了 Netty 框架相关的一些功能,如获取该 Channel 的 EventLoop。在传统的网络编程中,作为核心类的Socket ,它对程序员来说并不是那么友好,直接使用其成本还是稍微高了点。而 Netty 的 Channel 则提供的一系列的 API ,它大大降低了直接与 Socket 进行操作的复杂性。而相对于原生 NIO 的 Channel,Netty 的 Channel 具有如下优势 :

在 Channel 接口层,采用 Facade 模式进行统一封装,将网络 I/O 操作、网络 I/O相关联的其他操作封装起来,统一对外提供。Channel 接口的定义尽量大而全,为 SocketChannel 和 ServerSocketChannel提供统一的视图,由不同子类实现不同的功能,公共功能在抽象父类中实现,最大程度地实现功能和接口的重用。具体实现采用聚合而非包含的方式,将相关的功能类聚合在 Channel 中,由 Channel 统一负责和调度,功能实现更加灵活。

四、EventLoop && EventLoopGroup

Channel为Netty 网络操作抽象类,EventLoop 负责处理注册到其上的 Channel 处理 I/O 操作,两者配合参与 I/O 操作。EventLoopGroup 是一个 EventLoop 的分组,它可以获取到一个或者多个 EventLoop 对象,因此它提供了迭代出 EventLoop 对象的方法。

下图是 Channel、EventLoop、Thread、EventLoopGroup 之间的关系:

EventLoopGroup可以理解为线程池,EventLoop理解为一个线程,每个EventLoop对应一个Selector,负责处理多个Channel上的事件。

第一个boss EventLoopGroup分配一个EventLoop负责创建Channels传入的连接请求。一旦连接接受,第二个work EventLoopGroup分配一个 EventLoop给它的Channel。

一个 EventLoopGroup 包含一个或多个 EventLoop ,即EventLoopGroup : EventLoop = 1: n

一个 EventLoop 在它的生命周期内,只能与一个 Thread 绑定,即EventLoop : Thread = 1 : 1 。

所有有 EventLoop 处理的 I/O 事件都将在它专有的 Thread 上被处理,从而保证线程安全,即Thread :EventLoop = 1 : 1

一个 Channel 在它的生命周期内只能注册到一个 EventLoop 上,即Channel : EventLoop = n : 1 。

一个 EventLoop 可被分配至一个或多个 Channel ,即EventLoop : Channel = 1 : n

当一个连接到达时,Netty 就会创建一个 Channel,然后从 EventLoopGroup 中分配一个 EventLoop 来给这个 Channel 绑定上,在该 Channel 的整个生命周期中都是有这个绑定的 EventLoop 来服务的。

五、ChannelFuture

Netty 为异步非阻塞,即所有的 I/O 操作都为异步的,因此,我们不能立刻得知消息是否已经被处理了。Netty 提供了 ChannelFuture 接口,通过该接口的 #addListener(...) 方法,注册一个 ChannelFutureListener,当操作执行成功或者失败时,监听就会自动触发返回结果。

六、ChannelHandler

ChannelHandler ,连接通道处理器,我们使用 Netty 中最常用的组件。ChannelHandler 主要用来处理各种事件,这里的事件很广泛,比如可以是连接、数据接收、异常、数据转换等。ChannelHandler 有两个核心子类ChannelInboundHandler 和 ChannelOutboundHandler

ChannelInboundHandler 用于接收、处理入站( Inbound )的数据和事件ChannelOutboundHandler 则相反,用于接收、处理出站( Outbound )的数据和事件。
ChannelInboundHandler 的实现类还包括一系列的 Decoder 类,对输入字节流进行解码。ChannelOutboundHandler 的实现类还包括一系列的 Encoder 类,对输入字节流进行编码。ChannelDuplexHandler 可以同时用于接收、处理入站和出站的数据和时间。

ChannelHandler 还有其它的一系列的抽象实现 Adapter ,以及一些用于编解码具体协议的 ChannelHandler 实现类。

七、ChannelPipeline

ChannelPipeline 为 ChannelHandler 的链,提供了一个容器并定义了用于沿着链传播入站和出站事件流的 API 。一个数据或者事件可能会被多个 Handler 处理,在这个过程中,数据或者事件经流 ChannelPipeline ,由 ChannelHandler 处理。在这个处理过程中,一个 ChannelHandler 接收数据后处理完成后交给下一个 ChannelHandler,或者什么都不做直接交给下一个 ChannelHandler。

当一个数据流进入 ChannelPipeline 时,它会从 ChannelPipeline 头部开始,传给第一个 ChannelInboundHandler 。当第一个处理完后再传给下一个,一直传递到管道的尾部。与之相对应的是,当数据被写出时,它会从管道的尾部开始,先经过管道尾部的“最后”一个ChannelOutboundHandler ,当它处理完成后会传递给前一个 ChannelOutboundHandler 。当 ChannelHandler 被添加到 ChannelPipeline 时,它将会被分配一个 ChannelHandlerContext ,它代表了 ChannelHandler 和 ChannelPipeline 之间的绑定

其中 ChannelHandler 添加到 ChannelPipeline 中,通过 ChannelInitializer 来实现,过程如下:

一个 ChannelInitializer 的实现对象,被设置到了 BootStrap 或 ServerBootStrap 中。当 ChannelInitializer.initChannel() 方法被调用时,ChannelInitializer 将在 ChannelPipeline 中创建一组自定义的 ChannelHandler 对象。ChannelInitializer 将它自己从 ChannelPipeline 中移除。ChannelInitializer 是一个特殊的 ChannelInboundHandlerAdapter 抽象类

八、ChannelHandlerContext

保存Channel相关的所有上下文信息,同时关联一个ChannelHandler。ChannelHandlerContext中也绑定了对应的pipeline和Channel信息,方便对ChannelHandler进行调用

九、ChannelOption

Netty创建Channel实例后,可以通过ChannelOption设置channel参数。

参数

参考文章

参考文章

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。