服务启动
Netty 服务启动 的基础上,补充2方面的信息

  • ChannelConfig 配置信息
  • ChannelHandlerContext 和 ChannelHandler的一点补充.
  • Pipeline 事件流转详情

ChannelConfig 配置信息

  1. public NioServerSocketChannel(ServerSocketChannel channel) {
  2. super(null, channel, SelectionKey.OP_ACCEPT);
  3. config = new NioServerSocketChannelConfig(this, javaChannel().socket());
  4. }

出生于 NioServerSocketChannel 反射生成之时,它本身就是是静态内部类,寄生于 NioServerSocketChannel
image.png
看名字就知道是用来保留一些配置的,例如 Socketoption , 除此之外, Netty 的一些配置也放置在这里,例如 读取和写入 的大小. 如果调节buffer容量的大小.

最为重要的配置就是其内部持有了一个 AdaptiveRecvByteBufAllocator 实例,用于自动调节buffer的大小,可以在你需要的时候多一点(不囊中羞涩),不需要的时候少一点(不浪费). 具体是如何调节的,在读取消息环节进行解读.

ChannelHandlerContext 和 ChannelHandler

在服务启动一节稍微介绍了这两者的关系.
image.png
它们互相引用, 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

  1. I/O Request
  2. via {@link Channel} or
  3. {@link ChannelHandlerContext}
  4. |
  5. +---------------------------------------------------+---------------+
  6. | ChannelPipeline | |
  7. | \|/ |
  8. | +---------------------+ +-----------+----------+ |
  9. | | Inbound Handler N | | Outbound Handler 1 | |
  10. | +----------+----------+ +-----------+----------+ |
  11. | /|\ | |
  12. | | \|/ |
  13. | +----------+----------+ +-----------+----------+ |
  14. | | Inbound Handler N-1 | | Outbound Handler 2 | |
  15. | +----------+----------+ +-----------+----------+ |
  16. | /|\ . |
  17. | . . |
  18. | ChannelHandlerContext.fireIN_EVT() ChannelHandlerContext.OUT_EVT()|
  19. | [ method call] [method call] |
  20. | . . |
  21. | . \|/ |
  22. | +----------+----------+ +-----------+----------+ |
  23. | | Inbound Handler 2 | | Outbound Handler M-1 | |
  24. | +----------+----------+ +-----------+----------+ |
  25. | /|\ | |
  26. | | \|/ |
  27. | +----------+----------+ +-----------+----------+ |
  28. | | Inbound Handler 1 | | Outbound Handler M | |
  29. | +----------+----------+ +-----------+----------+ |
  30. | /|\ | |
  31. +---------------+-----------------------------------+---------------+
  32. | \|/
  33. +---------------+-----------------------------------+---------------+
  34. | | | |
  35. | [ Socket.read() ] [ Socket.write() ] |
  36. | |
  37. | Netty Internal I/O Threads (Transport Implementation) |
  38. +-------------------------------------------------------------------+