衆所周知,netty是高性能的緣由源於其使用的是NIO,可是這只是其中一方面緣由,其IO模型上決定的。另外一方面源於其線程模型的設計,良好的線程模型設計,可以減小線程上下文切換,減小甚至避免鎖的競爭(無鎖化設計)帶來的開銷。java
本篇文章將介紹netty的線程模型設計,主要從如下幾個方面:react
Reactor模式是一種軟件程序設計模式,它由Jim Coplien和Douglas C. Schmidt在1995年發佈,主要用於處理一個或者多個客戶端發起請求。設計模式
從一個客戶端鏈接到日誌服務器,而後發送請求的兩個流程來看Reactor模式。其中有三種組件:服務器
以上的幾種組件的做用和處理鏈接和請求事件的模式就是Reactor模式。網絡
以上的Reactor模式只是簡單的設計模型,對於每種程序語言設計而言,仍然須要作一些改變。基於Java的NIO如何使用該模式構建高性能可伸縮的服務,併發大神Doug Lea在他的網站上發佈過一篇論文《Scalable IO in Java》。多線程
這篇論文中主要談及的話題是如何構建高性能可擴展的IO,其中就是基於Reactor模式進行了演進。併發
其中涉及到如下組件:ide
在整個過程當中都是使用單線程,不管是Reactor線程和後續的Handler處理都只使用一個線程。oop
可是單線程無疑會下降性能,因此須要增長線程提供擴展。性能
爲了可以提升擴展性,須要在單線程的模型上增長線程,主要從兩個方面利用多線程發揮多核的應用優點:
以上多線程的Reactor處理模式中,Reactor線程仍然是單線程,負責acceptor和IO read/send。可是對於請求的解碼以及業務處理和響應的編碼都是有work thread pool負責。
上述的多線程模式解決了Handler下降Reactor的響應,同時也提高了Handler的處理效率。可是Reactor仍然是單線程,對於大量的網絡事件,其仍然有負載壓力。爲了可以使用多線程分擔壓力,演進出多Reactor:
其中主Reactor響應用戶的鏈接事件,而後分發給acceptor,由其建立新的子Reactor。多個子Reactor分別處理各自的IO事件,好比read/write,而後再將其交給work thread pool進行解碼,業務處理,編碼。
多Reactor的設計經過將TCP鏈接創建和IO read/write事件分離至不一樣的Reactor,從而分擔單個Reactor的壓力,提高其響應能力。
在認識了Reactor設計模式和基於Reactor構建高性能可擴展的IO後,再來看netty的線程模型就顯得簡單的多了。
netty的線程模型設計正是Reactor模式的變種。以上的三種Reactor模式,在netty中都能很是好的獲得了支持。在netty中主要經過參數配置來切換以上的各類模式。
netty中有EventLoopGroup和EventLoop兩個類,它們是實現Reactor的關鍵之所在。EventLoop正如其名,其中包包含一個Selector選擇器和一段循環邏輯。經過不斷循環獲取Selector上的就緒事件而後進行處理。EventLoopGroup是包含一組EventLoop的組,經過其能夠產生一個EventLoop。
在閱讀了netty官網給出的Demo後,能夠知道,在建立一個Server時都會建立兩個EventLoopGroup,分別爲boss和work。前者用戶Main Reactor,後者用於Sub Reactor和WorkThreadPool。
每次Main Reactor經過Selector獲得客戶端創建鏈接的請求後,就從work EventLoopGroup中獲取一個EventLoop,而後將創建的鏈接對應的Socket抽象SocketChannel綁定到EventLoop上,造成了新的Sub Reactor。
在瞭解了netty的線程模型後,下面首先看下各類模式下的netty的參數配置。
經過構造一個EventLoop,將其用做Reactor和WorkThread,便是單線程模式。
EventLoopGroup eventLoopGroup = new NioEventLoopGroup(); EventLoop bossLoop = eventLoopGroup.next(); EventLoop workLoop = reactorLoop; ServerBootstrap b = new ServerBootstrap(); b.group(reactorLoop, workLoop);
boss和work使用同一個EventLoop,能夠實現單線程Reactor。
Reactor使用單線程,而後Work使用多線程,便是多線程模型。
EventLoopGroup eventLoopGroup = new NioEventLoopGroup(); EventLoop bossLoop = eventLoopGroup.next(); EventLoopGroup workLoopGroup = new NioEventLoopGroup(); ServerBootstrap b = new ServerBootstrap(); b.group(reactorLoop, workLoopGroup);
以上的多線程Reactor模式,即是多Reactor模式。bossLoop是主Reactor,其經過事件循環建立TCP鏈接,而後將鏈接的SocketChannel抽象綁定到workLoopGroup中的EventLoop上,造成Sub Reactor。
只是Main Reactor是單線程進行事件循環。雖然也能夠構造多線程,可是沒有什麼實際意義。由於netty中在綁定端口時只會使用Group中的一個EventLoop綁定到Selector上,便是使用了EventLoopGroup。
固然對於同個應用若是監聽多個端口,使用多個ServerBootStrap共享一個boss,那樣Main Reactor也是多線程模式,纔有意義。