1. 程式人生 > >Netty原始碼 服務端的啟動

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.初始化 

 

初始化只做了兩件事

  1. 將配置屬性設定到channelConfig或者channel 中
  2. 加入新連線處理器

p.addLast()向serverChannel的流水線處理器中加入了一個 ServerBootstrapAcceptor,從名字上就可以看出來,這是一個接入器,專門接受新請求,把新的請求扔給某個事件迴圈器

3.註冊

將該條channel繫結到一個selector上去,一個selector被一個reactor執行緒使用,後續該channel的事件輪詢,以及事件處理,非同步task執行都是由此reactor執行緒來負責

 

現在我們的channel已經和reactor執行緒繫結在一起了,現在就剩下最後一步了,完成埠的繫結。

netty通過非同步執行緒的方式完成埠繫結,這段程式碼比較難找,最終會來到 io.netty.channel.DefaultChannelPipeline.HeadContext#bind

 

 最終調到了jdk裡面的bind方法,這行程式碼過後,正常情況下,就真正進行了埠的繫結。