ChannelPipeline

当 Channel 被创建时,它将会被自动地分配一个新的 ChannelPipeline。这项关联是永久性的;Channel 既不能附加另外一个 ChannelPipeline,也不能分离其当前的。在 Netty 组件的生命周期中,这是一项固定的操作,不需要开发人员的任何干预。
使得事件流经 ChannelPipeline 是 ChannelHandler 的工作,它们是在应用程序的初始化或者引导阶段被安装的。这些对象接收事件、执行它们所实现的处理逻辑,并将数据传递给 链中的下一个 ChannelHandler。它们的执行顺序是由它们被添加的顺序所决定的

  • ChannelPipeline 是一个 Handler 的集合,它负责处理和拦截 inbound 或者 outbound 的事件和操作,相当于一个贯穿 Netty 的链。(也可以这样理解:ChannelPipeline 是 保存 ChannelHandler 的 List,用于处理或拦截 Channel 的入站事件和出站操作)
  • ChannelPipeline 实现了一种高级形式的拦截过滤器模式,使用户可以完全控制事件的处理方式,以及 Channel 中各个的 ChannelHandler 如何相互交互
  • 一个 Channel 包含了一个 ChannelPipeline,而 ChannelPipeline 中又维护了一个由 ChannelHandlerContext 组成的双向链表,并且每个 ChannelHandlerContext 中又关联着一个 ChannelHandler
  • 入站事件和出站事件在一个双向链表中,入站事件会从链表 head 往后传递到最后一个入站的 handler,出站事件会从链表 tail 往前传递到最前一个出站的 handler,两种类型的 handler 互不干扰

image.png
ChannelPipeline 提供了ChannelHandler 链的容器,并定义了用于在该链上传播入站和出站事件流的API。 当ChannelHandler 被添加到ChannelPipeline 时,它将会被分配一个ChannelHandlerContext,其代表了ChannelHandler 和ChannelPipeline 之间的绑定。

ChannelPipeline 的API

  • addFirst、addBefore、addAfter、addLast 将一个 ChannelHandler 添加到 ChannelPipeline 中
  • remove 将一个 ChannelHandler 从 ChannelPipeline 中移除
  • replace 将 ChannelPipeline 中的一个 ChannelHandler 替换为另一个 ChannelHandler
  • get 通过类型或者名称返回 ChannelHandler
  • context 返回和 ChannelHandler 绑定的 ChannelHandlerContext
  • names 返回 ChannelPipeline 中所有 ChannelHandler 的名称

ChannelPipeline 的 API 公开了用于调用入站和出站操作的附加方法。

ChannelPipeline 上数据的流动顺序

入站和出站 ChannelHandler 可以被安装到同一个 ChannelPipeline 中。
如果一个消息或者任何其他的入站事件被读取,那么它会从 ChannelPipeline 的头部开始流动,最终,数据将会到达 ChannelPipeline 的尾端,届时,所有处理就都结束了。
数据的出站运动(即正在被写的数据)在概念上也是一样的。在这种情况下,数据将从链的尾端开始流动,直到它到达链的头部为止。在这之后,出站 数据将会到达网络传输层,这里显示为 Socket。通常情况下,这将触发一个写操作。

如果将两个类别的ChannelHandler都混合添加到同一个ChannelPipeline 中会发生什么

虽然 ChannelInboundHandle 和 ChannelOutboundHandle 都扩展自 ChannelHandler,但是 Netty 能区分 ChannelInboundHandler 实现和 ChannelOutboundHandler 实现,并确保数据只会在具有相同定向类型的两个 ChannelHandler 之间传递
image.png
站在逻辑视图的角度,分属出站和入站不同的Handler ,是无所谓顺序的。 而同属一个方向的Handler则是有顺序的,因为上一个Handler处理的结果往往是下一个Handler的要求的输入。 将图中的处理器(ChannelHandler)从左到右进行编号,那么入站事件按顺序看到的ChannelHandler 将是1,2,4,而出站事件按顺序看到的ChannelHandler 将是5,3。