前先后后利用工做之余的闲暇时间阅读Netty源码有一个月了,如今Netty各组件之间的联系,已经有了一个初步的认识。但文章还停留在笔记的整理阶段,只能当成我的笔记看。此文为Netty系列的第一篇,主要描述一个客户端请求在Netty中流转的整个生命周期,它通过了哪些组件之间相互配合。后面的文章会对每个组件进行源码分析,以及此文没有体现出来的组件它们的做用。如
ChannelFuture
、ByteBuf
等。在阅读以前,推荐先阅读下以前的一篇文章(浅谈NIO中的Reactor设计模式应用)。html
Ractor
模型的Multiple Reactors Version
是浅谈NIO中的Reactor设计模式应用中的3.3,DougLea在Scalable IO in Java
画的模型图以下所示: java
mainReactor
的acceptor
只负责接收客户端的链接事件,subReactor
只负责网络
读写I/O
事件,其实subReactor
能够有多个,这样减轻每一个subReactor
负载。对于耗时compute业务代码,能够交给线程池处理,处理后注册写事件返回给客户端。acceptor
和subReactor
都轮询本身的selector.select()
,处理着本身"感兴趣"的事件。其实Netty底层模型应用即是这种,只不过各组件的名字和做用都有些差别。设计模式
/**
* 举个例子:如今我想一个accptor和多个subReactor。
**/
// 一个Acceptor
EventLoopGroup parentEventLoopGroup = new NioEventLoopGroup(1);
// 当前CPU核数*2的subReactor个数,对于如今超线程CPU那就再*n
EventLoopGroup childEventLoopGroup = new NioEventLoopGroup();
复制代码
对于selector、channel等组件的做用能够在浅谈NIO中的Reactor设计模式应用,本文只介绍Netty相关的组件用途,如下内容根据图自顶向下bash
NioEventLoopGroup
:直译这个类名就是nio
的事件轮询组,其实轮询的就是Selector.select()
。文档中的解释是"it is used for NIO Selector based Channel."。对于接收客户端的链接事件与selectionKey绑定的是ServerSocketChannel;对于读写网络I/O
事件与selectionKey绑定的即是SocketChannel。NioEventLoop
:经过名称就能够看出来,它即是事件轮询组中的一个轮询,也就是一个subReactor
或者acceptor
(一般作法在建立接收链接的轮询组时都是建立一个)。ChannelPipeline
:文档中的解释是"it handles or intercepts inbound events and outbound operations of a implements an advanced form of the Intercepting Filter pattern",翻译过来就是它处理或者是拦截入栈事件和出栈的一些操做,实现了一种更加高级的拦截过滤器模式。过滤器模式是入出走同一个过滤器,而对于ChannelPipeline
入栈处理和出栈处理分离开了,ChannelPipeline
底层维护着一个ChannelHandlerContext
双向链表。ChannelPipeline
的处理流程以下:
Channel
里读出来的数据,须要通过与Channel
绑定的ChannelPipeline
中的InboundHandler
处理,再注册写事件。写出的时候须要经ChannelPipeline
中的OutboundHandler
处理在写回给客户端。ChannelHandlerContext
:ChannelPipeline
中是ChannelHandlerContext
双向链表,它起到一个承上启下的做用,意思是可以向上获取到ChannelPipeline
和Channel
,又能向下获取到ChannelHandler
。ChannelInboundHandlerAdapter
/ChannelOutboundHandlerAdapter
:入栈出栈的处理器对象,它应用适配器设计模式,后续文章中咱们在从细节分析。ServerBootStrapAcceptor
:Netty
中acceptor
对象,用于将EventLoop
中Selector
接收到的Channel
(这里面其实与selectionKey
绑定的是serverChannel
而后再经过serverChannel.accept()
获得的),将Channel
注册给ChildEventLoop
(这块Netty
是经过round-robin
去获取EventLoop
)中个其中一个Selector
上。