Netty学习之组件和设计
前言
前面我们简单地介绍了Netty,然后学习了一个简单的小例子,接下来我们来学习Netty的组件概要及组件之间的关系。
Channel,EventLoop,ChannelFuture
对于Netty来说,Channel、EventLoop、ChannelFuture三者的结合,就是Netty的网络抽象
- Channel代表的是Socket
- EventLoop代表的是控制流,多线程以及并发
- ChannelFuture代表的是异步通知
Channel接口
Netty中的Channel接口,减少了直接与Socket交互的复杂性,Netty中提供了众多的预定义Channel
- EmbeddedChannel
- LocalServerChannel
- NioDatagramChannel
- NioSctpChannel
- NioSocketChannel
- NioServerSocketChannel
EventLoop接口
EventLoop定义了Netty处理事件的核心抽象。
Netty中的Channel、EventLoop、Thread以及EventLoopGroup的关系如下
- 一个EventLoopGroup包含一个或者多个EventLoop
- 一个EventLoop在其生命周期中绑定一个线程
- 一个EventLoop处理的所有事件均由其对应的线程来处理(避免了同步需要加锁的问题)
- 一个Channel在其生命周期中注册唯一一个EventLoop
- 一个EventLoop可以同于处理一个或者多个Channel
具体的图例如下所示(图片来自《Netty In Action》)
ChannelFuture接口
在Netty中的所有操作都是异步的,因为所有的操作不太可能立即返回,所以我们需要有某个东西可以让我们在需要的时候来获取操作的结果,Netty中的ChannelFuture就是这个用途,通过其addListener()
方法来注册ChannelFutureListener
实例,可以在操作完成之后获得通知。
ChannelHandler,ChannelPipeline
如果说上面的三者是Netty的网络抽象,那么ChannelHanlder、ChannelPipeline就是Netty中的数据控制流以及应用的处理逻辑了。
ChannelHandler接口
从开发者的角度来讲,ChannelHandler是我们主要的操作对象,应用的操作逻辑都位于ChannelHandler中,ChannelHandler中的方法由网络事件进行触发和调用,ChannelHandler可以用于任何用途,比如讲数据从一个格式转换为另一种格式或者处理异常等。
有两个主要的子接口,ChannelInboundHandler、ChannelOutboundHandler,用于处理两种不同类型的数据(输入的数据以及输出的数据)
同时,在Netty中提供了很多Adapter,用于提高开发者的开发效率,并且这些适配器会自动将事件传递给下一个处理器
- ChannelHandlerAdapter
- ChannelInboundHandlerAdapter
- ChannelOutboundHanlderAdapter
- ChannelDuplexHandlerAdapter
编解码器
由于在网络中发送的数据都是二进制格式,所以,当使用Netty进行网络开发时,我们同样需要对数据进行编码和解码
编码用于将数据转换成二进制格式
解码用于将二进制格式转换成我们需要的格式
Netty中提供了一些常用的编解码器,这些编解码器本质上也是ChannelHandler,如ByteToMessageDecoder、MessageToByteEncoder
Channelpipeline接口
ChannelPipeline提供了将所有的ChannelHandler连接其他的容器,也就是说,在Netty中,所有的ChannelHandler通过ChannelPipeline串联起来。同时,ChannelPipeline提供了在该链中进行事件传播的方法。
ChannelPipeline通过下面的方式注册ChannelHandler
- ServerBootstrap注册一个ChannelInitializer的实现类
- 当ChannelInitializer.initChannel()被调用时,通过ChannelInitializer在ChannelPipeline注册一系列的ChannelHandler
- ChannelInitializer将自己从ChannelPipeline中移除
ChannelHandler根据初始化阶段注册的顺序在ChannelPipeline中传递事件。
Netty中的事件可以通过每个方法中的ChannelHandlerContext来传递给下一个Handler,由于我们通常只关注某一个事件,所以Netty提供了ChannelInboundHandlerAdapter以及ChannelOutboundHandlerAdapter。
在Netty中有两种方式可以发送数据
- 直接通过Channel发送,会从头到尾发送数据
- 通过ChannelHandler绑定的ChannelHandlerContext进行发送,只会讲数据传递给下一个ChannelHandler
Bootstrapping
Netty中的Bootstap类提供了应用的网络层配置的容器
根据对象的不同,有两种不同类型的bootstrap
- ServerBootstrap,用于绑定本地端口,需要两个EventLoopGroup(可以是同一个)
- bootstrap,用于连接远程主机及端口,只需要一个EventLoopGroup
一个服务器需要两种不同类型的Channel,一个是用于存放一个单一的用于表示服务器自己监听的ServerChannel,一个用于维护所有已经建立连接的Channel,也就是accept()操作之后的连接
总结
本小节我们主要学习Netty的核心组件概要及组件的关系,包括了Channel、EventLoop、EventLoopGroup、ChanneHandler、ChannelPipeline、Boostrap等,不同的组件有不同的功能,不同的组件之间又相互交互,共同构成完整的Netty应用。