Netty2020 3-2——Netty源码之Server端Boss线程组的启动

以主从Reactor为例,Server在启动的时候,会创建Boss和Worker两个EventLoopGroup,这两个group会作为参数传入到ServerBootstrap的group方法中。

1.Boss组线程的启动:

1) 用户线程部分:

AbsttractBootstrap.bind->绑定端口

AbsttractBootstrap.initAndRegister->初始化channel并注册channel

MultithreadEventLoopGroup.register

SingleThreadEventLoop.register

AbstractChannel.register

SingleThreadEventExecutor.execute

SingleThreadEventExecutor.startThread->这个只会在初始化的时候start一次,因为inEventLoop是false。

SingleThreadEventExecutor.doStartThread

ThreadPerTaskExecutor.execute->4.1.X新加入的方法,将用工厂创建线程并启动执行任务的动作封装了起来,也是真正启动Boss线程的地方,之前都是用户线程。

2) Boss线程部分:

SingleThreadEventExecutor.this.run

NioEventLoop.run->这里是一个死循环,在ratio不是100的时候,会一直跑任务,主要工作有两个:

NioEventLoop.processSelectedKeys 和 SingleThreadEventExecutor.runAllTasks。

下面先说下SingleThreadEventExecutor.runAllTasks。

3) Boss线程组创建并启动的线程数量

无论你在构造EventLoopGroup的时候的入参传入的nThreads是多少,真正创建并启动的Boss线程的个数只和bind的端口数有关。如果server只绑定了一个端口(大部分服务器都是只绑定一个端口),那么及时nThreads>1,那么也只会启动一个Boss线程。

因为这个线程的启动是bind动作的附属操作(bind中的register0),所以和bind的次数相关。

2.任务的添加和执行

接上面,在ThreadPerTaskExecutor.execute执行,也就是真正启动线程之后,执行取任务操作:

SingleThreadEventExecutor.runAllTasks->这里会取两种不同的task,定时任务也会被添加到taskQueue中

SingleThreadEventExecutor.fetchFromScheduledTaskQueue->最开始定时的task没有

SingleThreadEventExecutor.pollTask->普通task有一个元素,就是上面说的启动线程之前添加进去的register的task

AbstractEventExecutor.safeExecute->poll出来的任务都在这里执行

3.任务的添加和执行

在Boss线程组启动之前,SingleThreadEventExecutor.execute中会先添加一个task,该task是注册channel,这是第一个添加进去的任务register0:

AbstractChannel$AbstractUnsafe.register0

该任务又会衍生出两个其他任务,这两个衍生任务在register0方法中。

四个任务

1) 第一个衍生任务

invokeHandlerAddedIfNeeded:686, DefaultChannelPipeline

callHandlerAddedForAllHandlers:1161, DefaultChannelPipeline

execute:1487, DefaultChannelPipeline$PendingHandlerAddedTask

handlerAdded:107, ChannelInitializer->在上面添加完handler之后,初始化channel

initChannel:178, ServerBootstrap$1->向pipeline中添加ChannelHandler

execute:773, SingleThreadEventExecutor->添加的动作在这个execute中执行

SingleThreadEventExecutor->addTask->这里,该衍生任务添加到taskQueue中

所以,到此,又回到了上面提到的那个流程,只是这次在execute方法中,inEventLoop是true,不用再启动boss线程了。

2) 第二个衍生任务

safeSetSuccess:978, AbstractChannel$AbstractUnsafe

notifyListenersNow:485, DefaultPromise

notifyListener0:511, DefaultPromise

operationComplete:296, AbstractBootstrap$1

doBind0:362, AbstractBootstrap

execute:773, SingleThreadEventExecutor->这里又回到了熟悉的流程里

3) 第二个衍生任务又会衍生一个任务

接上面:

bind:254, AbstractChannel

bind:1019, DefaultChannelPipeline

bind:486, AbstractChannelHandlerContext

invokeLater:1012, AbstractChannel$AbstractUnsafe

SingleThreadEventExecutor.execute的4次执行

第一次,调用线程是用户线程,是bind->register的时候,register:479, AbstractChannel$AbstractUnsafe,会启动boss线程。

第二次,调用线程是Boss线程,register0:510, AbstractChannel$AbstractUnsafe,invokeHandlerAddedIfNeeded:686, DefaultChannelPipeline。

第三次,调用线程是Boss线程,register0:512, AbstractChannel$AbstractUnsafe,safeSetSuccess:978, AbstractChannel$AbstractUnsafe。

第四次,调用线程是Boss线程,bind:486, AbstractChannelHandlerContext,invokeLater:1012, AbstractChannel$AbstractUnsafe

对应的四次addTask添加任务

第一次,任务是register0

第二次,register0的衍生操作,pipeline.addLast,添加ChannelHandler

第三次,register0的衍生操作,doBind0中的Channel.bind操作

第四次,doBind0的衍生操作,bind:566, AbstractChannel$AbstractUnsafe,invokeLater:1012, AbstractChannel$AbstractUnsafe,task任务是pipeline.fireChannelActive()

 

后面会详解一下pipeline.fireChannelActive注册连接事件这块。

 

 

你可能感兴趣的:(netty)