购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

1.4 Netty框架模块介绍

Netty是一个高性能、异步事件驱动的NIO通信框架,是基于JAVA NIO提供的API所实现的。本节介绍Netty框架中的主要功能模块,让读者有一个基本认识。

1.4.1 Netty框架功能模块的组织结构

关于Netty框架功能模块的组织结构,请参考由Netty官网(netty.io)提供的原理结构图,如图1.23所示。

图1.23 Netty框架功能模块的组织结构图(引自netty.io)

Netty框架主要由三个功能模块组成,分别是核心(Core)功能模块、传输服务(Transport Services)功能模块和协议支持(Protocol Support)功能模块。

其实,这幅关于Netty框架功能模块的组织结构图比较抽象,这里大致介绍一下。

· 核心(Core)功能模块:用于核心功能的定义与实现。

◆ Zero-Copy-Capable Rich Byte Buffer:支持零拷贝的字节缓冲(Rich Byte Buffer表示多字节的缓冲对象),实现了Netty框架版本的Byte Buffer功能(针对JDK的Byte Buffer功能进行了强大的优化)。

◆ Universal Communication API:通用通信API。

◆ Extensible Event Model:可扩展的事件模型。

· 传输服务(Transport Services)功能模块:用于具体网络传输的定义与实现。

◆ In-VM pipe:内部JVM传输管道的实现。

◆ HTTP Tunnel:HTTP传输协议的实现。

◆ Socket Datagram:Socket TCP、Socket UDP传输协议的实现。

· 协议支持(Protocol Support)功能模块:相关协议的支持。

◆ 借助单元测试的传统文本、二进制协议。

◆ 压缩、大文件传输协议、实时流传输协议。

◆ Http & WebSocket、SSL、StartTLS、Google Protobuf等协议。

1.4.2 Netty Bootstrap入口模块

Netty Bootstrap模块相当于Netty框架的启动器,因此也称为入口模块,主要包括Bootstrap接口和ServerBootstrap接口,如图1.24所示。

图1.24 Netty框架—Bootstrap入口模块

如图1.24中的箭头所示,在io.netty.bootstrap模块中定义了Bootstrap接口类和ServerBootstrap接口类。其中,Bootstrap接口主要负责客户端的启动,ServerBootstrap接口主要负责服务端的启动。

Bootstrap接口类和ServerBootstrap接口类在启动过程中,主要功能是创建、初始化和配置核心的Channel对象。

1.4.3 Netty Channel传输通道模块

Channel传输通道模块是Netty框架网络操作的抽象类,主要包括基本的I/O操作(例如:bind、connect、read、write等)。另外,Channel传输通道模块还包括了Netty框架相关的一些功能,比如如何获取该Channel模块的事件驱动循环对象(EventLoop,详见后文)。关于Netty框架中Channel模块的组织结构,如图1.25所示。

图1.25 Channel传输通道模块(一)

Netty框架设计Channel模块的目的,主要是为了解决传统套接字(Socket)网络编程中的烦琐不易之处。相信但凡有过套接字(Socket)网络编程开发经验的读者一定深有感触,使用底层Socket开发网络应用的难度大,且成本高,一不小心就会掉入各种陷阱之中耗费精力。

而Netty框架设计出的Channel模块很好地解决了上述问题,它所提供的一系列API,极大地降低了直接使用套接字(Socket)进行网络开发的难度。尤其是针对原生Java NIO的开发,Netty框架的Channel模块较好地解决了诸多痛点。

例如,像Channel接口API采用了Facade模式进行统一封装,将网络I/O操作及其相关的其他操作统一封装起来,很好地为SocketChannel接口和ServerSocketChannel接口提供了统一的视图,如图1.26所示。

图1.26 Channel传输通道模块(二)

Channel模块是使用了聚合(非包含)的方式来实现的,将相关功能聚合在Channel之中进行统一的管理与调度。其中,NioSocketChannel接口基于Java NIO实现了Netty框架下的TCP协议的NIO传输,如图1.27所示。

图1.27 Channel传输通道模块(三)

1.4.4 Netty EventLoop事件循环模块

Netty框架是基于事件驱动模型的,具体是使用相应的事件来通知状态改变或者操作状态改变。前一小节介绍的Channel模块是Netty框架网络操作的抽象类,本小节介绍的EventLoop模块主要用于Channel模块实现I/O操作处理,这两个模块配合在一起来参与并完成I/O操作。

Netty框架设计的EventLoop模块实现了控制流、多线程和并发功能,结合Channel模块能够帮助用户实现周期性的任务调度。比如:当一个客户端连接到达时,Netty就会注册一个Channel对象,然后由EventLoopGroup接口(可以理解为EventLoop接口组合)分配一个EventLoop对象绑定到这个Channel对象上。此时这个Channel对象在整个生命周期中,都是由这个绑定的EventLoop对象来提供相应的服务。

根据Netty官方文档中的解释,对于Channel、Thread(线程)、EventLoop和EventLoopGroup之间的关系大致总结如下:

· 一个EventLoopGroup对象包含一个或多个EventLoop对象。

· 一个EventLoop对象在其生命周期内只能绑定一个Thread对象。

· 凡是由EventLoop对象处理的I/O事件都由其所绑定的Thread对象来处理。

· 一个Channel对象在其生命周期内只能注册一个EventLoop对象。

· 一个EventLoop对象可能被分配处理多个Channel对象(即EventLoop与Channel是1:n的关系)。

· 一个Channel对象上所有的ChannelHandler事件由其所绑定的EventLoop对象中的I/O线程进行处理。

· 千万不要阻塞Channel对象的I/O线程,这可能会影响该EventLoop对象中所包含的其他Channel对象的事件处理。

1.4.5 Netty ChannelFuture异步通知接口

Netty框架被设计为异步非阻塞方式,即所有I/O操作都为异步的,也就是应用程序不会马上得知客户端发送的请求是否已经被服务器端处理完成了。

因此,Netty框架设计了一个ChannelFuture异步通知接口,通过该接口定义的addListener()方法注册一个ChannelFutureListener对象,当操作执行成功或者失败时,监听对象就会自动触发并返回结果。

1.4.6 ChannelHandler与ChannelPipeline接口

ChannelHandler接口是Netty框架中的核心部分,是负责管理所有I/O数据的应用程序逻辑容器。具体来讲,ChannelHandler就是用来管理连接请求、数据接收、异常处理和数据转换等功能的接口。

ChannelHandler接口有两个核心子类:ChannelInboundHandler和ChannelOutboundHandler。其中,ChannelInboundHandler子类负责处理输入数据和输入事件,而ChannelOutboundHandler子类负责处理输出数据和输出事件,具体如图1.28所示。

图1.28 Netty框架—ChannelHandler接口

ChannelPipeline接口则为ChannelHandler接口提供了一个容器,并定义了用于沿着链传播输入和输出事件流的API。一个数据或者事件可能会被多个Handler处理,在这个过程中,数据或事件流经ChannelPipeline接口后交由ChannelHandler接口处理,具体如图1.29所示。

图1.29 Netty框架—ChannelPipeline接口

在这个处理过程中,一个ChannelHandler对象接收输入数据并处理完成后交给下一个ChannelHandler对象,或者什么都不做直接交给下一个ChannelHandler对象进行处理。

当一个数据流进入ChannlePipeline时,会从ChannelPipeline头部开始传给第一个ChannelInboundHandler 。当第一个处理完后再传给下一个,一直传递到ChannlePipeline的尾部。相反地,当一个数据流写出时,其会从管道尾部开始操作,当处理完成后会传递给前一个ChannelOutboundHandler对象。

当ChannelHandler对象被添加到ChannelPipeline对象时,其会被分配一个ChannelHandlerContext,代表了ChannelHandler和ChannelPipeline之间的绑定。其中,ChannelHandler对象被添加到ChannelPipeline对象的过程如下:

(1)一个ChannelInitializer对象的实现被注册到了ServerBootStrap对象上。

(2)当ChannelInitializer.initChannel方法被调用时,ChannelInitializer将在ChannelPipeline中安装一组自定义的ChannelHandler。

(3)ChannelInitializer将它自己从ChannelPipeline中移除。 QdOajZYsJ0TWLbxJaL3GtIKxZCK/Tk2uE9y1Vtr6xf2h+RGDakJGuuxD/5usO4ia

点击中间区域
呼出菜单
上一章
目录
下一章
×