
一文聊透Netty IO事件的编排利器pipeline |详解所有IO事件(一)
1. 前文回顾
在前边的系列文章中,笔者为大家详细剖析了 Reactor 模型在 netty 中的创建,启动,运行,接收连接,接收数据,发送数据的完整流程,在详细剖析整个 Reactor 模型如何在 netty 中实现的过程里,我们或多或少的见到了 pipeline 的身影。
Reactor启动后的结构.png
比如在 Reactor 启动的过程中首先需要创建 NioServerSocketChannel ,在创建的过程中会为 NioServerSocketChannel 创建分配一个 pipeline ,用于对 OP_ACCEPT 事件的编排。
当 NioServerSocketChannel 向 main reactor 注册成功后,会在 pipeline 中触发 ChannelRegistered 事件的传播。
当 NioServerSocketChannel 绑定端口成功后,会在 pipeline 中触发 ChannelActive 事件的传播。
主从Reactor组完整结构.png
又比如在 Reactor 接收连接的过程中,当客户端发起一个连接并完成三次握手之后,连接对应的 Socket 会存放在内核中的全连接队列中,随后 JDK Selector 会通知 main reactor 此时 NioServerSocketChannel 上有 OP_ACCEPT 事件活跃,最后 main reactor 开始执行 NioServerSocketChannel 的底层操作类 NioMessageUnsafe#read 方法在 NioServerSocketChannel 中的 pipeline 中传播 ChannelRead 事件。
传播ChannelRead事件.png
最终会在 NioServerSocketChannel 的 pipeline 中的 ServerBootstrapAcceptor 中响应 ChannelRead 事件并创建初始化 NioSocketChannel ,随后会为每一个新创建的 NioSocetChannel 创建分配一个独立的 pipeline ,用于各自 NioSocketChannel 上的 IO 事件的编排。并向 sub reactor 注册 NioSocketChannel ,随后在 NioSocketChannel 的 pipeline 中传播 ChannelRegistered 事件,最后传播 ChannelActive 事件。
传播ChannelRegister事件.png
还有在《Netty如何高效接收网络数据》一文中,我们也提过当 sub reactor 读取 NioSocketChannel 中来自客户端的请求数据时,会在 NioSocketChannel 的 pipeline 中传播 ChannelRead 事件,在一个完整的 read loop 读取完毕后会传播 ChannelReadComplete 事件。
在《一文搞懂Netty发送数据全流程》一文中,我们讲到了在用户经过业务处理后,通过 write 方法和 flush 方法分别在 NioSocketChannel 的 pipeline 中传播 write 事件和 flush 事件的过程。
笔者带大家又回顾了一下在前边系列文章中关于 pipeline 的使用场景,但是在这些系列文章中并未对 pipeline 相关的细节进行完整全面地描述,那么本文笔者将为大家详细的剖析下 pipeline 在 IO 事件的编排和传播场景下的完整实现原理。
内容概要.png
2. pipeline的创建
主从Reactor组完整结构.png
Netty 会为每一个 Channel 分配一个独立的 pipeline ,pipeline 伴随着 channel 的创建而创建。
前边介绍到 NioServerSocketChannel 是在 netty 服务端启动的过程中创建的。而 NioSocketChannel 的创建是在当 NioServerSocketChannel 上的 OP_ACCEPT 事件活跃时,由 main reactor 线程在 NioServerSocketChannel 中创建,并在 NioServerSocketChannel 的 pipeline 中对 OP_ACCEPT 事件进行编排时(图中的 ServerBootstrapAcceptor 中)初始化的。
无论是创建 NioServerSocketChannel 里的 pipeline 还是创建 NioSocketChannel 里的 pipeline , 最终都会委托给它们的父类 AbstractChannel 。
image.png
在前边的系列文章中笔者多次提到过,pipeline 的结构是由 ChannelHandlerContext 类型的节点构成的双向链表。其中头结点为 HeadContext ,尾结点为 TailContext 。其初始结构如下:
pipeline的初始结构.png
