1. 程式人生 > >從源碼角度解析Netty的React模式是如何工作的

從源碼角度解析Netty的React模式是如何工作的

簡單 net multi 邏輯 初始化 lec RKE con acceptor

Netty 支持多種實現方式,比如nio,epoll 等,本文以nio的實現方式進行講解。

1.EventLoop :

事件循環看,簡單來說就是一個死循環監聽事件,如果事件來了,處理掉。通常做法就是開啟一個獨立線程,一直循環。

偽代碼:

while (queue.waitForMessage()) {
queue.processNextMessage();
}

2.EventLoopGroup:

一組(多個)事件循環。

3.bossGroup 和 workGroup

EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();

server端bossGroup 是負責 NioServerSocketChannel 處理客戶端連接請求的,一個應用程序如果只開了一個端口(嚴格來說就是沒有多個ServerBootstrap公用一個
bossGroup),那麽 bossGroup 只需要一個eventLoop 就行了,如果配置大於1也沒關系(因為用不到,eventLoop也不會啟動)

ServerSocketChannel 創建好後,就綁定到網絡端口就開始監聽,如果有新的客戶端連接進來,那麽accept()後就會產生 SocketChannel,一個連接對應一個 SocketChannel

偽代碼:

ServerSocketChannel ssc = ServerSocketChannel.open();
...
SocketChannel socketChannel = ssc.accept();

為了提高服務器性能,所有有的
SocketChannel 的相關操作都是在workGroup中完成的,所以 workGroup 裏面需要配置適當多個 EnventLoop.

4.源碼層面講解 一個 ServerSocketChannel 只需要一個 EventLoop.

->bind(100).sync(); 綁定端口

-->AbstractBootstrap.doBind 具體綁定動作

---->AbstractBootstrap.initAndRegister config().group().register(channel); 將 serverChannel註冊到bossGroup 的某個eventLoop中

------>MultithreadEventLoopGroup.register next().register(channel); next() 方法負責從group 中挑選一個eventLoop ,具體是由 chooser.next()實現;

通俗來講就是,創建一個serverChannel綁定端口,初始化端口的過程中是從bossGroup中挑選一個 eventLoop,將channel註冊到eventLoop中,eventLoop中nio selector,完成channel的註冊。

註冊的核心代碼是:

技術分享圖片

如果當前線程就是在enventLoop ,調用register 方法就是直接執行register0,否則向線程(池)提交一個任務(eventLoop.execute()),這就是Reactor模式的核心實現邏輯,通過任務完成線程調配。

提交任務時候會幹什麽呢?

技術分享圖片

以上完整過程具體來講就是,main線程開啟(創建)一個serverChannel,創建過程中會從bossGroup 中選擇一個eventLoop 給該channel, 同時給eventLoop 提交第一個任務(註冊),同時會啟動eventLoop ,

eventLoop 線程會掃描執行自己任務池裏面的任務,其實第一個任務就是註冊(將serverChannel註冊到selector上),同時也會在自己線程中開始事件循環(接受客戶端的連接)。

技術分享圖片

NioEventLoop 一直在幹兩件事:a.處理selector 上的 io 事件; b.其他其他線程提交過來的task。

5.上面講了bossGroup 幹的事情,下面將一下workGroup 是如何工作的,其實和bossGroup 一樣,因為他們公用的是同一套代碼邏輯,

不同點是每一個 SocketChannel (ServerSocketChannel.accept) 初始化時候,都會從workGroup裏面選擇一個 eventLoop.

技術分享圖片

ServerBootstrapAcceptor 核心代碼:

技術分享圖片

ServerChannel channelRead 實際上是產生的一個連接,就是一個child channel ,然後從childGroup.rigister 的意思和上面serverChannel的一樣,完成註冊,其實也是通過提交任務實現的,只不過這裏提交的是scheduledTask,這裏註冊挑選的child eventLoop 可能是已經啟動了的(一個eventLoop負責多個child channel 的監聽)

這樣就實現了bossGroup負責連接, childGroup負責連接後的具體IO讀寫操作, 一個ServerBootstrap 只有一個enventLoop,childGroup 需要有多個(性能方面的需要)。


從源碼角度解析Netty的React模式是如何工作的