以主從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註冊連接事件這塊。