服务启动
在 Netty 服务启动 的基础上,补充2方面的信息
- ChannelConfig 配置信息
- ChannelHandlerContext 和 ChannelHandler的一点补充.
- Pipeline 事件流转详情
ChannelConfig 配置信息
public NioServerSocketChannel(ServerSocketChannel channel) {
super(null, channel, SelectionKey.OP_ACCEPT);
config = new NioServerSocketChannelConfig(this, javaChannel().socket());
}
出生于 NioServerSocketChannel
反射生成之时,它本身就是是静态内部类,寄生于 NioServerSocketChannel
看名字就知道是用来保留一些配置的,例如 Socket
的 option
, 除此之外, Netty
的一些配置也放置在这里,例如 读取和写入
的大小. 如果调节buffer容量的大小.
最为重要的配置就是其内部持有了一个 AdaptiveRecvByteBufAllocator
实例,用于自动调节buffer的大小,可以在你需要的时候多一点(不囊中羞涩),不需要的时候少一点(不浪费). 具体是如何调节的,在读取消息环节进行解读.
ChannelHandlerContext 和 ChannelHandler
在服务启动一节稍微介绍了这两者的关系.
它们互相引用, Context
作为 pipeline
流水线上的一个节点,节点上触发的事件(业务逻辑)则由对应的 Handler
来进行处理.
介绍一下图中节点的作用
实线: 代表直接引用 虚线: 相对直接引用的关系弱一点(但是它们本质还是直接引用)
- Head(DefaultChannelPipeline.HeadContext): 流水线的头部节点,即是一个InBound Handler也是一个OutBound Handler. 意味着它既可以处理入事件同时也处理出事件,具体看实现. 详情到下一个小节描述.
- Context 上下文信息,主要是持有Handler和Channel的引用,并将各个事件触发给Handler处理.
- Handler 事件处理
- Tail(DefaultChannelPipeline.TailContext): 流水线的尾部节点,和Head一样,同时处理出事件和入事件. 具体和实现相关.
由于链表结构的特殊性事件往往是从头部流转到尾部的. 如下这些事件的发生往往是在头部开始到达Tail
- channelRegistered 注册事件(注册啥呢?)
- channelActive 激活
- channelRead 从Socket读取一次完整的数据完成后触发
- channelReadComplete 从Socket完成一次读取事件后触发
- channelInactive 关闭时
- userEventTriggered 用户事件
- exceptionCaught 出现异常时
- read/write/register/bind/connect/close 等等
Pipeline 事件流转
上小节主要描述了Context和Handler的关系,以及触发事件时,事件沿着流水线从头部开始送达尾部,期间不断的被流水线上的Context所引用的Handler进行二次加工处理.
这节主要讲述下流转的细节,例如
- 什么是InBound和OutBound
Read读事件究竟是从哪里触发的. 又是如何被各个Handler所加工的(消息读取是描述)- ChannelActive 从哪里触发的,又是如何被Context处理的
等等.
InBound和OutBound
I/O Request
via {@link Channel} or
{@link 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) |
+-------------------------------------------------------------------+