ChannelPipeline源碼分析

pipeline的初使化

  • pipeline的創建:pipeline在創建channel(無論是客服端的channel還是服務端的channel)的時候被創建。
  • Netty裏目前只有一個pipeline的實現, 也就是DefaultChannelPipeline,構造方法如圖:
  • 在Netty裏,業務邏輯是以寫對應的ChannelHandler來實現的,在Netty的內部,會將ChannelHandler封裝成ChannelHandlerContext對象,然後以鏈表的雙鏈表的形式進行組織。AbstractChannelHandlerContext部分代碼如下:
  • 在pipeline裏有head和tail兩個屬性,分別指向channelHandlerContext的頭結點和尾結點,其中HeadContext內部有unsafe對象,可以通過unsafe處理讀寫事件。代碼如下:
  • TailContext的inbound屬性設置爲true

添加ChannelHandler

DefaultChannelPipeline提供了往鏈表裏增加節點的方法,增加一個ChannelHandler包括如下幾個步驟
  • 判斷是否重複添加
  • 創建節點並添加到雙鏈表中
  • 回調添回完成事件

刪除ChannelHandler

刪除channleHandler的入口如下圖:
  • 找結點
  • 刪除結點
  • 回調事件

事件與異常的傳播

channelHandler在大類上可以分爲InboundHandler與outboundHandler。類圖如下:

我們在寫業務方法的時候,可以通過pipeline對象fire某個事件,也可以用ChannelHandlerContext 對象fire某個事件。兩種方式都會進行事件的傳播,兩個的區別是通過pipeline fire的事件是從雙鏈表的頭結點開始傳播的,而通過ChannelHandlerContext對象是從當前結點往下傳播 的

read事件的傳播分析(Inbound事件)

當連接監聽到有OP_READ事件後,會調用unsafe的read方法進行處理,下面來看看unsafe是如何處理事件的。

  • 處理channel read的入口
  • pipeline觸發read的入口
  • 調用head的invokeChannelRead方法
  • 最終會調用到channelHandler的channelRead方法
  • head結點的處理邏輯
  • 找到下一個類型爲inbound的channelHandler

  • 尾結點的處理邏輯,如果消息沒處理,則會打個warm日誌,並釋放bytebuf對象
write事件的傳播分析(Outbound事件)

在寫業務ChannelHandler的時候,如果是outbound類型的handler,可以重寫write方法,並通過ChannelHandlerContext對象調用write,讓write進行傳播,其中通過channel調用的write方法會從pipeline的tail結點開始傳播,而直接調用ChannelHandlerContext的write方法會從當前結點進行傳播。下面分析write事件如何在pipeline裏進行傳播

  • 事件傳播的入口
  • tail結點write處理邏輯
  • 找到前一個結點的處理邏輯
  • 調用handler的witer方法
  • 通過head結點的write方法,調用channel的unsafe對象,執行寫入操作
異常的傳播

當channelHandler在處理業務的時候發生了異常,異常信息會從當前的鏈上往下傳播,直到有一個channelHandler把異常處理了,如果沒有channelHandler把異常處理,會傳播到tail結點,在實際業務中,在channelHandler鏈的最後增加一個統一的異常處理下面分析異常的傳播流程

  • 異常傳播入口
  • 會調用到invokeExceptionCaught方法
  • 調用到hander的exceptionCaught方法
  • 在channelHandlerAdapter裏,默認會讓exception往下傳播
  • AbstractChannelHandlerContext異常傳播的邏輯,先當前結點的下一個結點
  • 傳到tail結點的邏輯
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章