一起說說Netty責任鏈,責任鏈這塊是netty運行機制的核心,一起來完整的了解下netty的責任鏈。
(一)責任鏈模式
介紹
責任鏈模式(Chain of Responsibility Pattern) 為請求創建了一個處理對象的鏈。一個請求過來後,就交給一個責任鏈進行調用。在責任鏈裡面定義很多很多的handler,具體請求這個程序的handler,請求者不關心,多少個步驟,多少次,只負責發送到責任鏈上,請求傳遞的細節不關心。
實現責任鏈模式
處理器抽象類,具體的處理器實現類,保存處理器信息,處理執行。
源碼分析
(二)Netty中的ChannelPipeline責任鏈
介紹
pipeline管道保存了通道所有處理器信息,創建channel時自動創建一個專有的pipeline,入站事件和出站事件會調用pipeline上的處理器。
入站事件和出站事件
入站事件:通常指IO線程生成了入站數據
(通俗理解:從socket底層自己往上冒上來的事件都是入站)
比如EventLoop收到selector的OP_READ事件,入站處理器調用socketChannel.read(ByteBuffer)接受到數據後,這將導致通道的ChannelPipeline中包含的下一個中的channelRead方法被調用
出站事件:通常指IO線程執行實際的輸出操作
(通俗理解:想主動往socket底層操作的事件的都是出站)
比如bind方法用時請求server socket綁定到給定的SocketAddress,這將導致通道的ChannelPipeline中包含的下一個出站處理器中的bind方法被調用
Nettty中定義的事件
Pipeline中的handler是什麼
ChannelHeadler
用於處理I/O事件或者攔截I/O操作,並轉發到ChannelPipeline中下一個處理器。這個頂級接口定義功能很弱,實際使用時會去實現下面兩大子接口:處理入站I/O事件的ChannelInboundHandler、處理出站I/O操作的ChannelOutboundHandler
適配器類
為了方便開發,避免所有handler去實現一遍接口方法,Netty提供了簡單的實現類:
ChannelInboundHandlerAdapter處理入站I/O事件
ChannelOutboundHandlerAdapter處理出站I/O事件
ChannelDuplexHandler支持同時處理入站和出站事件
ChannelHandlerContext
實際存儲在Pipeline中的並非是ChannelHandler,而是上下文對象。將Handler包裹在上下文對象中,通過上下文對象與它所屬的ChannelPipeline交互,向上或向下傳遞事件或者修改pipeline都是通過上下文對象。
那麼如何維護Pipeline中的handler呢
ChannelPipeline是線程安全的,ChannelHandler可以在任何時候添加或者刪除。例如你可以在即將交換敏感信息時插入加密處理程序,並在交換後刪除它。一般操作,初始化的時候增加進去,較少刪除。下面是Pipeline中管理的API
除了register方法還有bind方法,bind方法時出站事件執行順序和入站事件相反
請求過來以後又是如何處理的呢?我們通過Accept事件獲取請求,所以我們應該去看accept入站事件是如何處理的,
PS:用戶在管道中有一個或者多個channelhandler來接收I/O事件(例如讀取)和請求I/O操作(例如寫入和關閉)一個典型的伺服器在每個通道的管道中都有以下處理程序,但是根據協議和業務邏輯的複雜性和特徵,可能會有所不同。
協議解碼器--將二進位數據(例如ByteBuf)轉換為Java對象
協議編碼器--將java對象轉化為二進位數據
業務邏輯處理程序--執行實際的業務邏輯(例如訪問資料庫)