Netty(六)—关于Pipeline

Netty之Pipeline

  • 不管时Netty客户端和服务端,都出现了Pipeline的身影
  • 从之前的学习可以大致了解到
    • 在Netty中每个Channel都有且仅有一个ChannelPipeline与之对应

官方解释

  • ChannelPipeline注释,从注释中对ChannelPipeline有了进一步的认识
    • 在ChannelPipeline中存放了ChannelHandler列表,用来处理或拦截出站和入站事件。这些在一个Channel对象中完成
    • 每一个Channel拥有自己的ChannelPipeline,当Channel对象被创建的时候,随之创建

在这里插入图片描述

ChannelPipeline结构

  • 通过ChannelPipeline的构造方法进行跟踪,在DefaultChannelPipeline中完成初始化
    • 通过代码可以发现,ChannelPipeline中维护了一个由ChannelHandlerContext组成的双向链表
    • 链表尾部和头部分别是 TailContextHeadContext
    • 并且每一个 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的关系

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章