Netty原始碼 服務端的啟動
最近一直在看netty,看完之後就想做點筆記。可是實在是太忙了,擠了還要幾個晚上終於擠出來了
上圖是服務端的例項程式碼。大致的流程先梳理一遍。
首先會執行 用於建立兩個執行緒組,boosGroup用於接受外部連線,對 SelectionKey.OP_ACCEPT 感興趣
,workGroup用於處理io操作,內部,每當有新連線進來的時候boosGroup 都會把連線封裝成一個channel 交給workGroup 去處理。
我們再看 NioEventLoopGroup 的構造方法,一直點進去,實際上呼叫的 MultithreadEventExecutorGroup
可以看到 這兩行程式碼實際就是建立兩個包含 NioEventLoop 物件的陣列。NioEventLoop物件我們後面介紹。
ServerBootstrap 是一個輔助類,主要用於設定各種配置引數,
.group(bossGroup, workerGroup)
就是上面我們建立的兩個執行緒組,bossGroup
的作用就是不斷地accept到新的連線,將新的連線丟給workerGroup
來處理
.channel(NioServerSocketChannel.class)
表示服務端啟動的是nio相關的channel,channel在netty裡面是一大核心概念,可以理解為一條channel就是一個連線或者一個服務端bind動做
.childHandler(new ChannelInitializer<SocketChannel>)
表示一條新的連線進來之後,該怎麼處理
上面的幾行程式碼都是做相應配置。
真正的關鍵在於bind方法
我們一路點選進去。這個幹了三件事 初始化,註冊,繫結埠。
我們先看 initAndRegister
總共三步,建立channel,初始化,註冊。
1.建立 反射呼叫,這裡的clazz是在中設定的,所以這裡創建出的是NioServerSocketChannel
2.初始化
初始化只做了兩件事
- 將配置屬性設定到channelConfig或者channel 中
- 加入新連線處理器
p.addLast()
向serverChannel的流水線處理器中加入了一個 ServerBootstrapAcceptor
,從名字上就可以看出來,這是一個接入器,專門接受新請求,把新的請求扔給某個事件迴圈器
3.註冊
將該條channel
繫結到一個selector
上去,一個selector被一個reactor執行緒使用,後續該channel
的事件輪詢,以及事件處理,非同步task執行都是由此reactor執行緒來負責
現在我們的channel
已經和reactor
執行緒繫結在一起了,現在就剩下最後一步了,完成埠的繫結。
netty通過非同步執行緒的方式完成埠繫結,這段程式碼比較難找,最終會來到 io.netty.channel.DefaultChannelPipeline.HeadContext#bind
最終調到了jdk裡面的bind方法,這行程式碼過後,正常情況下,就真正進行了埠的繫結。