學一學Netty中的NioEventLoopGroup
- 一個Netty程序啓動時,至少要指定一個EventLoopGroup
- 假如我們使用NIO,那我們通常使用NioEventLoopGroup
- 使用BIO,那我們可以初始化OioEventLoopGroup
官方DOC
- 上圖時Netty(4.1.6)中EventLoopGroup的解釋
- 在事件循環期間可對EventExecutorGroup進行Channel的註冊,然後供後續使用
- 到這裏有一個模糊的概念,EventLoopGroup可以對Channel進行註冊
方法實現
- 通過其提供的接口方法可以發現EventLoopGroup定義了Channel的註冊規範
EventLoopGroup結構圖
父結構
- 這裏發現它的頂層父類是Executor對象。我們知道Netty是基於Java實現的RPC框架
- 那麼看到這裏不難理解,EventLoopGroup其實是和線程相關的
- Netty本質又是Reactor模型的實現,那麼EventLoopGroup和Reactor肯定是有關係的
EventLoopGroup與Reactor
- 還是熟悉的代碼
EventLoopGroup workerGroup = new NioEventLookGroup();
Bootstrap boot = new Bootstrap();
boot.group(workerGroup);
-
這裏初始化了一個NioEventLookGroup對象,那麼先來看一下EventLoopGroup的子結構
-
通過其子結構類圖可以發現一些端倪
SingleThreadEventLoop : 在一個線程中執行所有提交的任務
MultithreadEventLoopGroup : 多線程併發處理提交的任務
EmbeddedEventLoop : 用來測試
ThreadPerChannelEventLoop : 提供OIO的處理模式,每一個EventLoop對應一個線程對應一個Channel
通過NioEventLoopGroup窺視其冰山一角
- NioEventLoopGroup官方DOC
- 使用NIO模型,基於Channel選擇了Selector選擇器
- 初始化
- 未傳入參數的話,使用默認線程數。並且在初始化過程中創建一個SelectorProvider對象,後續用來提供Selector
- 默認線程數:處理器數 * 2
Bootstrap—group方法
- 客戶端實現
EventLoopGroup workerGroup = new NioEventLookGroup();
Bootstrap boot = new Bootstrap();
boot.group(workerGroup);
- 服務端實現
EventLoopGroup group = new NioEventLookGroup();
// 與客戶端不同,服務端使用 ServerBootstrap
ServerBootstrap boot = new ServerBootstrap();
boot.group(group);
- 服務端group方法實現
- 這裏我們可以發現,服務端的boss線程和worker線程實際上是同一個線程
- 到這裏我們可以發現,當我們設置單線程的時候。
- NioEventLoopGroup線程池的數量只設置爲1
- Netty中的Acceptor和後續所有的接收到的請求都是在一個線程中處理的
- 對應Reactor線程模型,就相當於Reactor的單線程模型
單線程模型
EventLoopGroup group = new NioEventLookGroup();
// 與客戶端不同,服務端使用 ServerBootstrap
ServerBootstrap boot = new ServerBootstrap();
boot.group(group);
多線程模型
// 設置 n > 1的線程數,當然要合理,不能無限大
EventLoopGroup group = new NioEventLookGroup(n);
// 與客戶端不同,服務端使用 ServerBootstrap
ServerBootstrap boot = new ServerBootstrap();
boot.group(group);
主從線程模型
EventLoopGroup boos = new NioEventLookGroup();
EventLoopGroup work = new NioEventLookGroup();
// 與客戶端不同,服務端使用 ServerBootstrap
ServerBootstrap boot = new ServerBootstrap();
boot.group(boos, worker);
- 看代碼,通過對parentGroup和childGroup進行不同的處理,確定其不同的工作職責
NioEventLoopGroup如何工作的
- 現在,對NioEventLoopGroup的作用以及原理有了一個基本的認識
- 那麼當任務過來的時候是如何被執行的呢
NioEventLoopGroup的實例化
- 通過其實例化過程入手
- 調用到 其父類 MultithreadEventLoopGroup 的構造方法,進行線程相關參數的設置
-
調用到 MultithreadEventExecutorGroup 的 構造方法,重點看其中的 newChild 方法
- 根據線程數量做循環
- 根據線程數量做循環
-
又回調到 NioEventLoopGroup 的 newChild 方法
- 走到 NioEventLoop 的構造方法
- 走到這裏看到了熟悉的方法openSelector()選擇器出現了