前先後後利用工做之餘的閒暇時間閱讀Netty源碼有一個月了,如今Netty各組件之間的聯繫,已經有了一個初步的認識。但文章還停留在筆記的整理階段,只能當成我的筆記看。此文爲Netty系列的第一篇,主要描述一個客戶端請求在Netty中流轉的整個生命週期,它通過了哪些組件之間相互配合。後面的文章會對每個組件進行源碼分析,以及此文沒有體現出來的組件它們的做用。如
ChannelFuture
、ByteBuf
等。在閱讀以前,推薦先閱讀下以前的一篇文章(淺談NIO中的Reactor設計模式應用)。html
Ractor
模型的Multiple Reactors Version
是淺談NIO中的Reactor設計模式應用中的3.3,DougLea在Scalable IO in Java
畫的模型圖以下所示: java
mainReactor
的acceptor
只負責接收客戶端的鏈接事件,subReactor
只負責網絡
讀寫I/O
事件,其實subReactor
能夠有多個,這樣減輕每一個subReactor
負載。對於耗時compute業務代碼,能夠交給線程池處理,處理後註冊寫事件返回給客戶端。acceptor
和subReactor
都輪詢本身的selector.select()
,處理着本身"感興趣"的事件。其實Netty底層模型應用即是這種,只不過各組件的名字和做用都有些差別。設計模式
/**
* 舉個例子:如今我想一個accptor和多個subReactor。
**/
// 一個Acceptor
EventLoopGroup parentEventLoopGroup = new NioEventLoopGroup(1);
// 當前CPU核數*2的subReactor個數,對於如今超線程CPU那就再*n
EventLoopGroup childEventLoopGroup = new NioEventLoopGroup();
複製代碼
對於selector、channel等組件的做用能夠在淺談NIO中的Reactor設計模式應用,本文只介紹Netty相關的組件用途,如下內容根據圖自頂向下bash
NioEventLoopGroup
:直譯這個類名就是nio
的事件輪詢組,其實輪詢的就是Selector.select()
。文檔中的解釋是"it is used for NIO Selector based Channel."。對於接收客戶端的鏈接事件與selectionKey綁定的是ServerSocketChannel;對於讀寫網絡I/O
事件與selectionKey綁定的即是SocketChannel。NioEventLoop
:經過名稱就能夠看出來,它即是事件輪詢組中的一個輪詢,也就是一個subReactor
或者acceptor
(一般作法在建立接收鏈接的輪詢組時都是建立一個)。ChannelPipeline
:文檔中的解釋是"it handles or intercepts inbound events and outbound operations of a implements an advanced form of the Intercepting Filter pattern",翻譯過來就是它處理或者是攔截入棧事件和出棧的一些操做,實現了一種更加高級的攔截過濾器模式。過濾器模式是入出走同一個過濾器,而對於ChannelPipeline
入棧處理和出棧處理分離開了,ChannelPipeline
底層維護着一個ChannelHandlerContext
雙向鏈表。ChannelPipeline
的處理流程以下:
從Channel
裏讀出來的數據,須要通過與Channel
綁定的ChannelPipeline
中的InboundHandler
處理,再註冊寫事件。寫出的時候須要經ChannelPipeline
中的OutboundHandler
處理在寫回給客戶端。ChannelHandlerContext
:ChannelPipeline
中是ChannelHandlerContext
雙向鏈表,它起到一個承上啓下的做用,意思是可以向上獲取到ChannelPipeline
和Channel
,又能向下獲取到ChannelHandler
。ChannelInboundHandlerAdapter
/ChannelOutboundHandlerAdapter
:入棧出棧的處理器對象,它應用適配器設計模式,後續文章中咱們在從細節分析。ServerBootStrapAcceptor
:Netty
中acceptor
對象,用於將EventLoop
中Selector
接收到的Channel
(這裏面其實與selectionKey
綁定的是serverChannel
而後再經過serverChannel.accept()
獲得的),將Channel
註冊給ChildEventLoop
(這塊Netty
是經過round-robin
去獲取EventLoop
)中個其中一個Selector
上。