咱們在使用Netty進行服務端開發的時候,通常來講會定義兩個NioEventLoopGroup線程池,一個"bossGroup"線程池去負責處理客戶端鏈接,一個"workGroup"線程池去負責處理讀寫操做。那麼,咱們爲何要這麼作呢?這樣作的好處是什麼呢?能不能只使用一個NioEventLoopGroup呢?這就是咱們今天要討論的主題——Netty的線程模型java
實際上Netty線程模型就是Reactor模式的一個實現,而Reactor模式又是什麼呢?react
Reactor模式是基於事件驅動開發的,核心組成部分包括Reactor和線程池,其中Reactor負責監聽和分配事件,線程池負責處理事件,而根據Reactor的數量和線程池的數量,又將Reactor分爲三種模型:bootstrap
圖片摘自:gee.cs.oswego.edu/dl/cpjslide…segmentfault
圖片摘自:gee.cs.oswego.edu/dl/cpjslide…markdown
單Reactor承當全部事件的監聽和響應,而當咱們的服務端遇到大量的客戶端同時進行鏈接,或者在請求鏈接時執行一些耗時操做,好比身份認證,權限檢查等,這種瞬時的高併發就容易成爲性能瓶頸多線程
Netty主要靠NioEventLoopGroup線程池來實現具體的線程模型的ide
單線程模型就是隻指定一個線程執行客戶端鏈接和讀寫操做,也就是在一個Reactor中完成,對應在Netty中的實現就是將NioEventLoopGroup線程數設置爲1,核心代碼是:高併發
NioEventLoopGroup group = new NioEventLoopGroup(1); ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(group) .channel(NioServerSocketChannel.class) .channel(NioServerSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .option(ChannelOption.SO_BACKLOG, 1024) .childHandler(new ServerHandlerInitializer()); 複製代碼
它的工做流程大體以下:oop
上述單線程模型就對應了Reactor的單線程模型
多線程模型就是在一個單Reactor中進行客戶端鏈接處理,而後業務處理交給線程池,核心代碼以下:
NioEventLoopGroup eventGroup = new NioEventLoopGroup(); ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(eventGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .option(ChannelOption.SO_BACKLOG, 1024) .childHandler(new ServerHandlerInitializer()); 複製代碼
走進group方法能夠發現咱們平時設置的bossGroup和workerGroup就是使用了同一個group
@Override public ServerBootstrap group(EventLoopGroup group) { return group(group, group); } 複製代碼
工做流程以下:
主從多線程模型是有多個Reactor,也就是存在多個selector,因此咱們定義一個bossGroup和一個workGroup,核心代碼以下:
NioEventLoopGroup bossGroup = new NioEventLoopGroup(); NioEventLoopGroup workerGroup = new NioEventLoopGroup(); ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup,workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .option(ChannelOption.SO_BACKLOG, 1024) .childHandler(new ServerHandlerInitializer()); 複製代碼
工做流程以下:
注意:其實在Netty中,bossGroup線程池最終仍是隻會隨機選擇一個線程用於處理客戶端鏈接,與此同時,NioServerSocetChannel綁定到bossGroup的線程中,NioSocketChannel綁定到workGroup的線程中
以上總結了Reactor的三種模型以及Netty中的對應實現,在Netty中,咱們使用的最多的仍是主從多線程模型。關於Reactor的學習,最權威的資料應該是Doug Lea大神的Scalable IO in Java,有興趣的同窗能夠看看