目录
前言
因为后两篇博客我打算针对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则是官方提供的一个便利父类,绝大部分方法的默认实现都是将事件传播给下/上一个节点。