常用的NIO框架-Netty( 二 )


该模型相比第二种模型 , 是将Reactor分成两部分 , mainReactor负责监听server socket , accept新连接;并将建立的socket分派给subReactor 。 subReactor负责多路分离已连接的socket , 读写网络数据 , 对业务处理功能 , 其扔给worker线程池完成 。 通常 , subReactor个数上可与CPU个数等同 。
2.3 Netty模型
2.2中说完了Reactor的三种模型 , 那么Netty是哪一种呢?其实Netty的线程模型是Reactor模型的变种 , 那就是去掉线程池的第三种形式的变种 , 这也是Netty NIO的默认模式 。 Netty中Reactor模式的参与者主要有下面一些组件:

  1. Selector
  2. EventLoopGroup/EventLoop
  3. ChannelPipeline
Selector即为NIO中提供的SelectableChannel多路复用器 , 充当着demultiplexer的角色 , 这里不再赘述;下面对另外两种功能和其在Netty之Reactor模式中扮演的角色进行介绍 。
3.EventLoopGroup/EventLoop当系统在运行过程中 , 如果频繁的进行线程上下文切换 , 会带来额外的性能损耗 。 多线程并发执行某个业务流程 , 业务开发者还需要时刻对线程安全保持警惕 , 哪些数据可能会被并发修改 , 如何保护?这不仅降低了开发效率 , 也会带来额外的性能损耗 。
【常用的NIO框架-Netty】为了解决上述问题 , Netty采用了串行化设计理念 , 从消息的读取、编码以及后续Handler的执行 , 始终都由IO线程EventLoop负责 , 这就意外着整个流程不会进行线程上下文的切换 , 数据也不会面临被并发修改的风险 。 这也解释了为什么Netty线程模型去掉了Reactor主从模型中线程池 。
EventLoopGroup是一组EventLoop的抽象 , EventLoopGroup提供next接口 , 可以总一组EventLoop里面按照一定规则获取其中一个EventLoop来处理任务 , 对于EventLoopGroup这里需要了解的是在Netty中 , 在Netty服务器编程中我们需要BossEventLoopGroup和WorkerEventLoopGroup两个EventLoopGroup来进行工作 。 通常一个服务端口即一个ServerSocketChannel对应一个Selector和一个EventLoop线程 , 也就是说BossEventLoopGroup的线程数参数为1 。 BossEventLoop负责接收客户端的连接并将SocketChannel交给WorkerEventLoopGroup来进行IO处理 。
EventLoop的实现充当Reactor模式中的分发(Dispatcher)的角色 。
4.ChannelPipelineChannelPipeline其实是担任着Reactor模式中的请求处理器这个角色 。
ChannelPipeline的默认实现是DefaultChannelPipeline , DefaultChannelPipeline本身维护着一个用户不可见的tail和head的ChannelHandler , 他们分别位于链表队列的头部和尾部 。 tail在更上层的部分 , 而head在靠近网络层的方向 。 在Netty中关于ChannelHandler有两个重要的接口 , ChannelInBoundHandler和ChannelOutBoundHandler 。 inbound可以理解为网络数据从外部流向系统内部 , 而outbound可以理解为网络数据从系统内部流向系统外部 。 用户实现的ChannelHandler可以根据需要实现其中一个或多个接口 , 将其放入Pipeline中的链表队列中 , ChannelPipeline会根据不同的IO事件类型来找到相应的Handler来处理 , 同时链表队列是责任链模式的一种变种 , 自上而下或自下而上所有满足事件关联的Handler都会对事件进行处理 。
ChannelInBoundHandler对从客户端发往服务器的报文进行处理 , 一般用来执行半包/粘包 , 解码 , 读取数据 , 业务处理等;ChannelOutBoundHandler对从服务器发往客户端的报文进行处理 , 一般用来进行编码 , 发送报文到客户端 。
下图是对ChannelPipeline执行过程的说明:
常用的NIO框架-Netty文章插图
5.BufferNetty提供的经过扩展的Buffer相对NIO中的有个许多优势 , 作为数据存取非常重要的一块 , 我们来看看Netty中的Buffer有什么特点 。


推荐阅读