Netty源码死磕(ChannelPipeline的执行过程)
引言
上文有提到如果Selector
轮询到网络IO事件了,则会调用该Channel
对应的ChannelPipeline
来依次执行对应的ChannelHandler
。
ChannelPipeline
和ChannelHandler
的关系
那么这里的ChannelPipeline
和ChannelHandler
之间到底是什么关系呢?
其实我们可以理解为类似于一个过滤器模式,其中ChannelPipeline
是一个存放各种过滤器的管道容器,而ChannelHandler
则对应着单个过滤器实体
执行流程
我们来看下ChannelPipline
的工作流程
NioEventLoop
触发读事件,会调用SocketChannel
所关联的ChannelPipline
- 由上一步读取到的消息会在
ChannelPipline
中依次被多个ChannelHandler
处理 - 处理完消息会调用
ChannelHandlerContext
的write
方法发送消息,发送的消息同样也会经过ChannelPipline
中的多个ChannelHandler
处理
上面的流程其实主要分成了两步,触发读事件和写事件。对应这两种事件,Netty
把ChannelHandler
也分为了两大类
ChannelInboundHandler
顾明思义,负责处理链路读事件的Handler
。通常由IO线程触发ChannelOutboundHandler
,负责链路写事件的Handler
也就是说当IO线程触发读事件时,只会调用ChannelInboundHandler
的实现handler
下面我们看下ChannelHandler
在ChannelPipline
中是一个什么样的结构
可以看到ChannelHandler
在加入ChannelPipline
之前会被封装成一个ChannelHandlerContext
节点类加入到一个双向链表结构中。除了头尾两个特殊的ChannelHandlerContext
实现类,我们自定义加入的ChannelHandler
最终都会被封装成一个DefaultChannelHandlerContext
类。
当有读事件被触发时,ChannelHandler
(会筛选类型为ChannelInboundHandler
的Handler) 的触发顺序是 HeaderContext
-> TailContext
当有写事件被触发时,ChannelHandler
(会筛选类型为ChannelOutboundHandler
的Handler) 的触发顺序与读事件相反是 TailContext
-> HeaderContext
总结
本文比较简短,主要是为了理清ChannelPipeline
和ChannelHandler
的关系,以及ChannelHandler
在ChannelPipeline
中的执行过程是怎样的