Netty中的ChannelHander詳解

爬蜥發表於2018-05-09

channelHandler是用來做什麼的?ChannelHandler用來處理元件之間的互動,結合它的狀態做各種業務,通過ChannelPipelinel來連線各個ChannelHandler

ChannelHandler怎麼在實際中使用?

channelHandler家族具有如下的結構

Netty中的ChannelHander詳解

  • ChannelInboundHandler用來處理入站資料以及各種狀態變化。ChannelInboundHandlerAdapter對介面做適配,預設簡單的提交到ChannelPipeline的下一個ChannelHandler,在實現過程中只需要專注重寫自己想要的方法即可,但是它不會自動的釋放與池化ByteBuf相關的記憶體,需要手動呼叫 ReferenceCountUtil.release()自動的實現在SimpleChannelInboundHandler,注意如果要傳遞給下一個ChannelHandler需要呼叫 ReferenceCountUtil.retain()
  • ChannelOutboundHandler處理出站資料並且允許攔截所有的操作。ChannelOutboundHandlerAdapter對介面做了適配,預設呼叫ChannelHandlerContext相同的方法,實現轉發到ChannelPipeline中的先一個ChannelHandler


Channel的各狀態詳解

Netty中的ChannelHander詳解

當channel狀態發生變化會轉換成對應的事件交給ChannelHandler處理

ChannelHandler的宣告週期詳解

  1. handlerAdded:新增到ChannelPipeline時呼叫
  2. handlerRemoved:從ChannelPipeline中移除時呼叫
  3. exceptionCaught:處理過程中在ChannelPipeline中有錯誤產生時呼叫。對於入站異常來講,從錯誤發生的那一點開始繼續沿著入站方向流動,所以一般在最後一個ChannelInboundHandler實現。【出站異常一般通過返回的ChannelFuture註冊listenner,通過 channelFuture.isSuccess 來判斷是否出現異常,另一種方式是將ChannelFutureListener作為引數給寫方法的ChannelPromise,他適合相對簡單的異常處理】

ChannelHandler在ChannelPipeline中的佈局是怎樣的?

Netty中的ChannelHander詳解

每個新建的channel都會被分配一個新的channelpipeline,而且在channel的整個生命週期中,這永遠不會被改變

ChannelPipeline是怎麼操作ChannelHandler?

  • addFirst(addLast):將channelhandler作為第一個(最後一個)處理器
  • addBefore(addAfter):在已經存在的channelhandler之前(之後)新增一個處理器
  • remove:從channelpipeline中刪除一個已經存在的channelhandler
  • replace:將原channelpipeline中的channelhandler替換成新的
  • fire開頭的方法:一般是呼叫channelpipeline中的下一個channelinboundchannelhandler對應的方法
  • 出站對應的write(read)則是寫(讀)channelpipeline的下一個channeloutboundhandler寫(讀)方法【其它出站方法類似】

ChannelHandlerContext與ChannelPipeline、ChannelHandler是什麼關係?

Netty中的ChannelHander詳解

ChannelHandlerContext用於管理它所關聯的ChannelHandler和同一個ChannelPipeline中的下一個ChannelHandler的互動【每當有handler新增到pipleline時,都會建立context,建立之後context和handler的關係永遠都不會變,因而可以快取context的引用】,如果事件從channel或者channelpipeline上觸發將沿整個pipeline傳播,但是context上的相同觸發方式只會傳遞給pipeline上的下一個能夠處理的handler

ChannelHandler是否可以在多個ChannelPipeline中複用?

在實現的handler上方使用註解@Sharable【注意ChannelHandler本身處理邏輯的執行緒安全性】,這樣多個pipeline就可以共享一個handler,這種方式可以用來收集跨多個channel的統計資訊





相關文章