Netty 線程模型
一、線程模型概述
線程模型表明了代碼的執行方式。從最開始的使用單線程,後來出現了多線程,之後是線程池。當有要執行的任務時,任務會被傳到線程池,從線程池中獲得空閑的線程來執行任務,執行完了後會將線程返回到線程池。
二、Reactor 模型
1.網絡服務基本的步驟:
①讀取請求 → ②解碼請求 → ③處理請求 → ④編碼響應 → ⑤發送響應
2.Reactor模型
(1)single threaded version
(圖片摘自Doug Lea的pdf,鏈接參見文末)
在這個模型中,一個線程處理所有I/O相關的操作。acceptor接收來自客戶端的TCP連接請求,建立連接後,通過dispatcher將消息(ByteBuffer)分發到各個handler(新的線程)上進行處理。這個模型無法滿足高容量的需求,不停的穿建了新的線程來處理消息,耗盡系統資源。此外,當NIO線程負載較重之後,處理速度會變慢導致大量客戶端連接超時,重新發送請求,導致CPU很快便會達到100。
(2)Multithreaded pattern
(圖片摘自Doug Lea的pdf,鏈接參見文末)
這個版本上的變化,主要體現在分發到各個handler(worker thread)時,使用了線程池,這樣避免創建過多的線程,控制線程數量,提高處理效率。 但是在個別場合,一個NIO線程負責監聽和處理所有客戶端連接(例如百萬客戶端連接)可能會存在性能問題。
(3)Multiple Reactor
(圖片摘自Doug Lea的pdf,鏈接參見文末)
在這個模型中,主reactor選擇一個線程作為acceptor線程,用於綁定監聽端口,接收客戶端連接。然後,Acceptor接收客戶端請求後創建新的SocketChannel,註冊到子reactor中進行握手等操作。最後,來到工作線程池,進行業務的操作。
三、Netty線程模型
1.接口EventLoop
1 public interface EventLoop extends OrderedEventExecutor, EventLoopGroup { 2 @Override 3 EventLoopGroup parent(); // 這個方法,返回這個EventLoop所屬的EventLoopGroup的引用 4 }
在Netty中,多個EventLoop會被創建。其中的一個用來服務多個Channnel,另外的其他,會用來優化資源的使用。這句話的意思,聯想代碼部分,我們可以想到下面:
1 EventLoopGroup bossGroup = newNioEventLoopGroup(1); //負責監聽接口,處理客戶端過來的連接請求 2 EventLoopGroup workerGroup = new NioEventLoopGroup(); //負責連接之後,通道的信息的傳輸
再看一下他的類的層次圖(圖摘自《Netty in action》):
2.Netty 4中I/O 和 事件處理
事件多種多樣,事件的本性決定了它本身如何被處理,例如:它可以從網絡往應用裏傳輸,也可相反,或是完全不同的一些事件。但是事件的處理邏輯要廣泛和靈活,以至於可以處理任何的情況。因此,在Netty 4中所有I/O和事件的處理交給 指定到EventLoop上的thread來執行。這點與Netty 3不同。
3.Netty 3中I/O 和 事件處理
只有Inbound事件會被交給EventLoop來執行,而所有Outbound事件會由調用者線程來執行,可能是I/O線程,也可能是其他線程。因此,outbound端需要同步的操作。因為,五法保證多個線程不會同時操作outbound事件。
4.實現的細節
看下面流程,線程的管理:
任務執行前會進行判斷,調用的線程是否是指定給EventLoop的線程。如果是同一個的話,直接執行任務;如果不是,將任務放進隊列之中,等EventLoop再次處理它的任務。
這就解釋了為什麽在ChannelHandler中為什麽不需要同步就可以讓線程和Channel直接交互。
就寫到這裏了。。。能力一般,水平有限!希望以後多用到Netty,能更好的認知Netty。
參考資料:
http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf
《Netty in action》
Netty 線程模型