Thursday, November 19, 2015

Classes related to Netty Transport - Part2

1. 相关流程

下面的相关流程特指NioServerSocketChannel/NioSocketChannel

1.1. bind流程

  • 新建一个Channel
  • 注册到boss group,注册时触发事件
    • fireChannelRegistered
    • fireChannelActive(如果是第一次注册,例如unregister后再register没有这个事件)
  • 调用Java NIO bind到端口

如下图:
  • Channel为NioServerChannel或相关子类中的实现
  • EventLoopGroup为NioEventLoopGroup或相关子类中的实现
  • EventLoop为NioEventLoop或相关子类中的实现
Server BootStrap
ServerBootStrap bind.png

1.2. accept流程

ServerBootstrap继承自AbstractBootStrap,前者在构造时需要两个EventLoopGroup:boss和worker 而后者在构造时,只需要一个EventLoopGroup。这是因为ServerBootstrap把需要bind和listen的Channel让父类处理,处理的逻辑定义在ServerBootstrapAcceptor:
  • 实现ChannelInboundHandlerAdapter
  • 当channelRead时(有新的Channel时),将childHander应用到该Channel上
  • 在worker group上注册这个新的Channel

1.3. connect流程

  • 新建一个Channel
  • 注册到boss group,注册时触发事件
    • fireChannelRegistered
    • fireChannelActive(如果是第一次注册,例如unregister后再register没有这个事件)
  • resolve name
  • 调用channel.connect

1.4. write流程

  • 用户调用Channel.write
  • 调用Pipeline.tail(TailContext)的write,默认实现是查找下一个个Outbound Context,并根据是否在eventloop,同步或异步的调用ChannelOutboundHandler.write函数
  • 我们定义一个ChannelOutboundHandler时,默认在最后也会调用context.write,因此又继续调用下一层
  • 最终,会调用到Pipeline.head(HeadContext)的write,默认实现时调用AbstractChannel中的write。
  • AbstractChannel的write默认是放到一个ChannelOutboundBuffer,只有flush时才真正write(细节由channel实现)

1.5. read流程

  • 读的发起地是NioEventLoop,在处理SelectionKey.OP_READ时发起。首先调用Channel的read(不同channel不同的实现)
  • channel的read中,一般读取网络数据后,调用Pipeline.fireChannelRead
  • 如上所述,Pipeline.fireChannelRead从head开始,向上查找Inbound Channel Handler,然后调用其invokeChannelRead
  • invokeChannelRead会根据是否在event loop中,同步或异步的调用channelRead函数,也就是我们一般会去override函数

0 评论: