Netty之Pipeline
- 不管时Netty客户端和服务端,都出现了Pipeline的身影
- 从之前的学习可以大致了解到
- 在Netty中每个Channel都有且仅有一个ChannelPipeline与之对应
官方解释
- ChannelPipeline注释,从注释中对ChannelPipeline有了进一步的认识
- 在ChannelPipeline中存放了ChannelHandler列表,用来处理或拦截出站和入站事件。这些在一个Channel对象中完成
- 每一个Channel拥有自己的ChannelPipeline,当Channel对象被创建的时候,随之创建
ChannelPipeline结构
- 通过ChannelPipeline的构造方法进行跟踪,在DefaultChannelPipeline中完成初始化
- 通过代码可以发现,ChannelPipeline中维护了一个由ChannelHandlerContext组成的双向链表
- 链表尾部和头部分别是 TailContext 和 HeadContext
- 并且每一个 ChannelHandlerContext 又关联这一个 ChannelHandler
- 可以理解为 每一个 tail 或 head 关联着一个 ChannelHandler
- 通过图更能清晰地看出其结构
- 接下来HeadContext和TailContext的类结构图
- 从类结构图中可以发现 Head 和 Tail 都实现了 ChannelHandlerContext 和 ChannelHandler
- 并且它们的初始化操作都是在 AbstractChannelHandlerContext 中完成的
- HeadContext 和 TailContext 初始化
- 可以发现Head初始化的时候outbound属性为true,而Tail初始化inbound属性为true
- 即Head是一个OutBound对象,而Tail是一个InBound对象
ChannelHandler和ChannelPipeline关联
- 无论是客户端和服务端,都使用到了 AbstractBootstrap 的 handler 或 childHandler 方法
- 我们可以在其中添加自定义Handler,如下代码示例
- 通过ChannelInitializer对象可以添加自定义Handler。addLast方法完成具体的添加操作,分为以下几个步骤
- 首先把传入的 channelInitializer 对象进行包装然后添加到链表中
- 向链表中添加我们的自定义handler,此时构造完成一个双向链表
- 需要注意的是 ChannelInitializer 继承了类 ChannelInboundHandlerAdapter
- 因此在链表中 除了 head 是 OutBound 其它节点全是 InBound (后续分析OutBound和InBound)
- 链表构建完成后,后续会对链表进行注册遍历,把Handler添加到Channel对应的Pipeline中
- 添加过程中移除最开始添加的ChannelInitializer
Pipeline事件传播机制
- AbstractChannelHandlerContext 有 inbound 和 outbound 两个变量用于标识 Context 对应的 handler 类型
- inbound -> true -> ChannelInboundHandler
- outbound -> true -> ChannelOutboundHandler
outbound事件传播
- outbound事件都是请求事件,即接收到请求之后通过outbound事件进行通知
- 以客户端发起connect请求为例,最终调用到DefaultChannelPipeline的connect方法
- 由此可以发现,outbound事件是以tail为起点开始传播调用的
- 然后调用AbstractChannelHandlerContext的connect方法
- findContextOutbound方法—以当前context为起点,向pipeline中的双向链表寻找一个outbound属性为ture的节点
- 结合之前的学习过程,这里实际上是传递到了head节点,因为head节点的outbound属性为true
- 所以connect消息传递给head后,会将消息传递给对应的ChannelHandler处理
- 最终connect方法在DefaultChannelPipeline的connect方法中由 unsafe 处理目标请求
- 处理逻辑流程图(该图片引用自咕泡学院Tom老师的课堂笔记)
inbound事件传播
-
inbound事件与outbound事件的处理方式类似,只是方向不同。即 head -> customContext -> tail
-
outbound事件都是请求事件,而inbound则是通知事件
-
inbound事件一般发生在Channel的状态改变或IO事件的就绪
-
处理逻辑流程图(图片引用自咕泡学院Tom老师的课堂笔记)
- 观察DefalutChannelPipeline的channelActive方法可以发现其channelActive方法是空的
- 因为inbound事件需要用户实现自定义的处理器
Handler深入
- 每一个ChannelHandler都会有一个ChannelHandlerContext与之关联
- ChannelHandlerContext允许ChannelHandler之间实现交互
- ChannelHandlerContext、ChannelHandler、ChannelPipeline的关系
与之关联
- ChannelHandlerContext允许ChannelHandler之间实现交互
- ChannelHandlerContext、ChannelHandler、ChannelPipeline的关系