1、业务处理流程

1.1 主从模型

1.2 Debug跟踪

我们用Netty源码包下面的example来Debug观察一下,包路径io.netty.example.echo

  • NioEventLoop#processSelectedKeysOptimized()方式循环处理不同的事件。如下图。
  • NioEventLoop#processSelectedKey方法处理一个事件,在该方法中的unsafe.read()这一行打断点(如1.2图), 这是NioEventLoop线程处理读(READ)事件和接受连接(ACCEPT)事件的代码。
  • 启动Server,Client发起请求。

1.3 BossGroup处理连接事件,第一次进入是ACCEPT事件

如图, 此时线程是nioEventLoopGroup-2-1,这是BossGroup,就是1.1图中的MainReactor。
unsafe类型AbstractNioMessageChannel.NioMessageUnsafe,这是处理连接事件的,入参ch(channel)类型是NioServerSocketChannel

1.4 跳过这一次循环,进入下一次循环,这次是READ事件

如图, 此时线程是nioEventLoopGroup-3-1,这是workerGroup,即是1.1图中的subReactor
unsafe类型AbstractNioByteChannel.NioByteUnsafe#read,这是处理读事件的,入参ch(channel)类型是NioSocketChannel

1.5 进入unsafe.read

这里是读取数据的逻辑,这个方法主要逻辑前面已经分析了,见Netty源码-业务流程之读事件
这里我们重点关注第4步,pipeline.fireChannelRead(byteBuf); 这里会转到我们自定义的handler处理数据。
pipeline是责任链模式

看一下Debug信息,如下图,pipeline有四个handler,通过双链表连接在一起,HeadContext和TailContext分别表示责任链的头和尾,第三个是我自定义的EchoServerHandler的,真个责任链将会被依次执行。

1.6 进入pipeline.fireCHannelRead,我们来到AbstractChannelHandlerContext#fireChannelRead

findContextInbound找到一个责任节点(Inbound类型)执行,MASK_CHANNEL_READ是channel read掩码。
MASK_ONLY_INBOUND(下图2)表示所有Inbound事件掩码集合,MASK_CHANNEL_READ和MASK_ONLY_INBOUND与运算结果不是0,就表示执行channelRead事件


1.7 最终会进入自定义Handler
最终达到我们自定义的channelRead逻辑,这里可以写我们自己的业务逻辑


杜若
67 声望3 粉丝