Netty(六)—關於Pipeline

Netty之Pipeline

  • 不管時Netty客戶端和服務端,都出現了Pipeline的身影
  • 從之前的學習可以大致瞭解到
    • 在Netty中每個Channel都有且僅有一個ChannelPipeline與之對應

官方解釋

  • ChannelPipeline註釋,從註釋中對ChannelPipeline有了進一步的認識
    • 在ChannelPipeline中存放了ChannelHandler列表,用來處理或攔截出站和入站事件。這些在一個Channel對象中完成
    • 每一個Channel擁有自己的ChannelPipeline,當Channel對象被創建的時候,隨之創建

在這裏插入圖片描述

ChannelPipeline結構

  • 通過ChannelPipeline的構造方法進行跟蹤,在DefaultChannelPipeline中完成初始化
    • 通過代碼可以發現,ChannelPipeline中維護了一個由ChannelHandlerContext組成的雙向鏈表
    • 鏈表尾部和頭部分別是 TailContextHeadContext
    • 並且每一個 ChannelHandlerContext 又關聯這一個 ChannelHandler
    • 可以理解爲 每一個 tail 或 head 關聯着一個 ChannelHandler
      在這裏插入圖片描述
  • 通過圖更能清晰地看出其結構

在這裏插入圖片描述

  • 接下來HeadContext和TailContext的類結構圖

在這裏插入圖片描述

  • 從類結構圖中可以發現 Head 和 Tail 都實現了 ChannelHandlerContext 和 ChannelHandler
  • 並且它們的初始化操作都是在 AbstractChannelHandlerContext 中完成的
    • HeadContext 和 TailContext 初始化

在這裏插入圖片描述
在這裏插入圖片描述

  • 可以發現Head初始化的時候outbound屬性爲true,而Tail初始化inbound屬性爲true
    • 即Head是一個OutBound對象,而Tail是一個InBound對象

ChannelHandler和ChannelPipeline關聯

  • 無論是客戶端和服務端,都使用到了 AbstractBootstrap 的 handler 或 childHandler 方法
  • 我們可以在其中添加自定義Handler,如下代碼示例

在這裏插入圖片描述

  • 通過ChannelInitializer對象可以添加自定義Handler。addLast方法完成具體的添加操作,分爲以下幾個步驟
    • 首先把傳入的 channelInitializer 對象進行包裝然後添加到鏈表中
    • 向鏈表中添加我們的自定義handler,此時構造完成一個雙向鏈表

在這裏插入圖片描述

  • 需要注意的是 ChannelInitializer 繼承了類 ChannelInboundHandlerAdapter
  • 因此在鏈表中 除了 head 是 OutBound 其它節點全是 InBound (後續分析OutBound和InBound)
  • 鏈表構建完成後,後續會對鏈表進行註冊遍歷,把Handler添加到Channel對應的Pipeline中
  • 添加過程中移除最開始添加的ChannelInitializer

在這裏插入圖片描述

Pipeline事件傳播機制

  • AbstractChannelHandlerContext 有 inbound 和 outbound 兩個變量用於標識 Context 對應的 handler 類型
  • inbound -> true -> ChannelInboundHandler
  • outbound -> true -> ChannelOutboundHandler

outbound事件傳播

  • outbound事件都是請求事件,即接收到請求之後通過outbound事件進行通知
  • 以客戶端發起connect請求爲例,最終調用到DefaultChannelPipeline的connect方法
    • 由此可以發現,outbound事件是以tail爲起點開始傳播調用的

在這裏插入圖片描述

  • 然後調用AbstractChannelHandlerContext的connect方法
    • findContextOutbound方法—以當前context爲起點,向pipeline中的雙向鏈表尋找一個outbound屬性爲ture的節點
    • 結合之前的學習過程,這裏實際上是傳遞到了head節點,因爲head節點的outbound屬性爲true

在這裏插入圖片描述

  • 所以connect消息傳遞給head後,會將消息傳遞給對應的ChannelHandler處理
  • 最終connect方法在DefaultChannelPipeline的connect方法中由 unsafe 處理目標請求

在這裏插入圖片描述

  • 處理邏輯流程圖(該圖片引用自咕泡學院Tom老師的課堂筆記)

在這裏插入圖片描述

inbound事件傳播

  • inbound事件與outbound事件的處理方式類似,只是方向不同。即 head -> customContext -> tail

  • outbound事件都是請求事件,而inbound則是通知事件

  • inbound事件一般發生在Channel的狀態改變或IO事件的就緒

  • 處理邏輯流程圖(圖片引用自咕泡學院Tom老師的課堂筆記)

在這裏插入圖片描述

  • 觀察DefalutChannelPipeline的channelActive方法可以發現其channelActive方法是空的
  • 因爲inbound事件需要用戶實現自定義的處理器

在這裏插入圖片描述

Handler深入

  • 每一個ChannelHandler都會有一個ChannelHandlerContext與之關聯
  • ChannelHandlerContext允許ChannelHandler之間實現交互
  • ChannelHandlerContext、ChannelHandler、ChannelPipeline的關係

與之關聯

  • ChannelHandlerContext允許ChannelHandler之間實現交互
  • ChannelHandlerContext、ChannelHandler、ChannelPipeline的關係

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章