1.BossGroup与WorkerGroup简单示意图如下:

2.首先搞清楚BossGroup和WorkerGroup中Channel分别如何产生与注册到Group中去的?
3.BossGroup中的Channel是何时以及如何创建的?
(1) 在ServerBootstrap.bind()绑定相应的地址时,会根据传入的channelClass类创建对应的ChannelFactory,在ServerBootstrap.initAndRegister()方法中
使用ChannelFactory反射实例化NioServerSocketChannel。
(2)初始化NioServerSocketChannel实例之后传入到ServerBootStrap.init(Channel)
设置Channel初始化值,如ChannelOptions,Attributes。
这边是利用一个ServerBootstrapAcceptor来监听channelRead事件,将新产生的channel绑定到childGroup (workerGroup),最终是绑定到WorkerGroup中某个EventLoop 中去。

4.BossGroup中的Channel是如何注册到BossGroup中的?
在以上初始化好NioServerSocketChannel之后,进行注册。config().group()其实是返回的parent group,即在我们初始化时,传入的BossGroup。

注:这边再详细说一下绑定过程
group().register(),其实通过代码跟进,它会通过Group中一个next()方法选择NioEventLoopGroup中一个NioEventLoop来具体进行绑定一个Channel对象。因为一个channel只能对应一个Eventloop。
SingleThreadEventLoop中 绑定关键代码如下:
public ChannelFuture register(final ChannelPromise promise)
{
ObjectUtil.checkNotNull(promise, "promise");
promise.channel().unsafe().register(this, promise);
return promise;
}可以看最终是调用Channel对象下的一个内部类UnSafe对象进行完成注册。
最终的注册动作是将真正的jdk channel绑定到的EventLoop中的Selector中去。每个channel绑定到Selector中之后,就会形成一个SelectionKey,会加入到EvenLoop中的keyset集合中去。方便在循环遍历时检查每个channel的状态。

5.WorkerGroup中的Channel是何时以及如何创建的?
在BossGroup启动之后,对应的NioEventLoopGroup线程池的NioEventLoop线程就会死循环检查已经绑定到对应的Selector上的Channel的I/O事件。
(1)当没有发生I/O事件时,NioEventLoop线程会一直堵塞在selector.select() 该方法上

(2)一旦有I/O过来之后,就会调用processSelectedKeys()去处理,循环检查SelectedKeys中的每个key,再进入processSelectedKey()。
(3)再调用对应发送符合事件的channel的unsafe.read() 方法。再该方法中会创建对应NioSocketChannel对象。

6.WorkerGroup中的Channel是如何注册到WorkerGroup中的?
从上面的小点中可以看出在NioServerSocketChannel发生了I/O事件中初始化了NioSocketChannel对象,下面就是需要将该对象中是如何注册到WorkerGroup中的解释了。
因为在创建NioServerSocketChannel实例是我们在其Pipeline中添加了ServerBootstrapAcceptor的InboundChannelHandler。并且如下图所示,在创建完Channel之后又将会会NioServerSocketChannel的Pipeline的channelread方法。这样在ServerBootstrapAcceptor中的channelread方法也会得到相应的触发。


7.对SevrerBootstrapAcceptor类简单概述
8.对UnSafe类简单概述
其实workgroup与bossgroup在监听I/O事件逻辑是一样(本身就是同一块代码实现),为什么会有不同read效果呢。从上面的分析,BossGroup会通过UnSafe.read()会有Channel实例产生,但是如果是wokergroup就不是这样的。
为什么呢?
那是因为NioServerSocketChannel 和 NioSocketChannel内部对unsafe的实现不一样。次啊会有此区别。每次与socket的交互还是会通过对应channel的unsafe类进行的。这样虽然BossGroup和Woke人Group共享NioEventLoop代码,但是由于其使用的Channel类型对应的UnSafe实现不一样才会导致对read方法调用有不一样的行为。

NioMessageUnsafe ---> AbstractNioMessageChannel、NioServerSocketChannel
NioByteUnsafe ---> AbstractNioByteChannel、NioSocketChannel