【Netty】Pipeline相关(四):inbound和outbound事件的区别

【Netty】Pipeline相关(四):inbound和outbound事件的区别

Scroll Down

目录

前言

因为后两篇博客我打算针对inbound和outbound的某个事件跟一下回调代码,所以现在这里写一篇博客记录一下inbound和outbound事件的区别。

本篇博客比较短,主要是摘自Netty的JavaDoc中,关于ChannelPipeline的描述。

文档版本:4.1.x


在这里我还想吐槽一下Netty的官方文档:像inbound和oubound概念区分这么重要的东西,怎么就不写在 https://netty.io 中呢?偏偏写在ChannelPipeline的JavaDoc中,要不是我有点追文档的习惯恰好看到,可能这辈子都无法区分inbound和outbound事件了。


事件是如何在pipeline中传播的

我们先来看看官方文档中给出的一张“图”:

                                                 I/O Request
                                            via Channel or
                                        ChannelHandlerContext
                                                      |
  +---------------------------------------------------+---------------+
  |                           ChannelPipeline         |               |
  |                                                  \|/              |
  |    +---------------------+            +-----------+----------+    |
  |    | Inbound Handler  N  |            | Outbound Handler  1  |    |
  |    +----------+----------+            +-----------+----------+    |
  |              /|\                                  |               |
  |               |                                  \|/              |
  |    +----------+----------+            +-----------+----------+    |
  |    | Inbound Handler N-1 |            | Outbound Handler  2  |    |
  |    +----------+----------+            +-----------+----------+    |
  |              /|\                                  .               |
  |               .                                   .               |
  | ChannelHandlerContext.fireIN_EVT() ChannelHandlerContext.OUT_EVT()|
  |        [ method call]                       [method call]         |
  |               .                                   .               |
  |               .                                  \|/              |
  |    +----------+----------+            +-----------+----------+    |
  |    | Inbound Handler  2  |            | Outbound Handler M-1 |    |
  |    +----------+----------+            +-----------+----------+    |
  |              /|\                                  |               |
  |               |                                  \|/              |
  |    +----------+----------+            +-----------+----------+    |
  |    | Inbound Handler  1  |            | Outbound Handler  M  |    |
  |    +----------+----------+            +-----------+----------+    |
  |              /|\                                  |               |
  +---------------+-----------------------------------+---------------+
                  |                                  \|/
  +---------------+-----------------------------------+---------------+
  |               |                                   |               |
  |       [ Socket.read() ]                    [ Socket.write() ]     |
  |                                                                   |
  |  Netty Internal I/O Threads (Transport Implementation)            |
  +-------------------------------------------------------------------+

从官方给出的图中,我们不难领悟到,inbound和outbound这两个词中的in和out就是相对于ChannelPipeline的。

  • 如果事件传播出ChannelPipeline,就是outbound事件
  • 如果事件是从外部传进ChannelPipeline的,就是inbound事件

传播顺序

从上面的图中,我们首先获得的第一印象是:

  • outbound事件是自顶向下传播的。
  • inbound事件则是自底向上传播的。

如果结合我前面的pipeline初始化添加ChannelHandler两篇博客,就很容易误以为:outbound事件是从head节点传播到tail节点,inbound事件是从tail节点传播到head节点。但实际上这个第一印象是错的,把这个第一印象反过来就对了。


官方文档也给出了解释顺序的例子,我们一起来看一下,假如有如下代码:

 ChannelPipeline p = ...;
 p.addLast("1", new InboundHandlerA());
 p.addLast("2", new InboundHandlerB());
 p.addLast("3", new OutboundHandlerA());
 p.addLast("4", new OutboundHandlerB());
 p.addLast("5", new InboundOutboundHandlerX());
  • 对于inbound事件传播,顺序是1,2,5,跟添加顺序相同。
  • 对于outbound事件传播,顺序是5,4,3,跟添加顺序相反。

后来我自己调试代码(将过程记录与后两篇博客),也确实是上述的顺序。


看看类图

看看ChannelInboundHandler、ChannelOutboundHandler两大方法的类图:

ChannelHandler在这一篇已经提到过了,这里就不再赘述。


ChannelInboundHandler

直接来看看这些方法:

  • 在我前面的博客中遇到过大部分,用官方的图来解释,即channel的变化事件传播,都是由Netty内部的I/O线程传播到pipeline的,属于inbound事件。

ChannelOutboundHandler

也是直接来看看它的方法:

  • 说明诸如绑定、读取新连接、写数据等操作,都是由pipeline传播到Netty内部的I/O线程的。

Adapter

ChannelInboundHandlerAdapter和ChannelOutboundHandlerAdapter则是官方提供的一个便利父类,绝大部分方法的默认实现都是将事件传播给下/上一个节点。