channelHandler是用來做什麼的?ChannelHandler用來處理元件之間的互動,結合它的狀態做各種業務,通過ChannelPipelinel來連線各個ChannelHandler
ChannelHandler怎麼在實際中使用?
channelHandler家族具有如下的結構
- ChannelInboundHandler用來處理入站資料以及各種狀態變化。ChannelInboundHandlerAdapter對介面做適配,預設簡單的提交到ChannelPipeline的下一個ChannelHandler,在實現過程中只需要專注重寫自己想要的方法即可,但是它不會自動的釋放與池化ByteBuf相關的記憶體,需要手動呼叫
ReferenceCountUtil.release()
自動的實現在SimpleChannelInboundHandler,注意如果要傳遞給下一個ChannelHandler需要呼叫ReferenceCountUtil.retain()
- ChannelOutboundHandler處理出站資料並且允許攔截所有的操作。ChannelOutboundHandlerAdapter對介面做了適配,預設呼叫ChannelHandlerContext相同的方法,實現轉發到ChannelPipeline中的先一個ChannelHandler
Channel的各狀態詳解
當channel狀態發生變化會轉換成對應的事件交給ChannelHandler處理
ChannelHandler的宣告週期詳解
- handlerAdded:新增到ChannelPipeline時呼叫
- handlerRemoved:從ChannelPipeline中移除時呼叫
- exceptionCaught:處理過程中在ChannelPipeline中有錯誤產生時呼叫。對於入站異常來講,從錯誤發生的那一點開始繼續沿著入站方向流動,所以一般在最後一個ChannelInboundHandler實現。【出站異常一般通過返回的ChannelFuture註冊listenner,通過
channelFuture.isSuccess
來判斷是否出現異常,另一種方式是將ChannelFutureListener作為引數給寫方法的ChannelPromise,他適合相對簡單的異常處理】
ChannelHandler在ChannelPipeline中的佈局是怎樣的?
每個新建的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是什麼關係?
ChannelHandlerContext用於管理它所關聯的ChannelHandler和同一個ChannelPipeline中的下一個ChannelHandler的互動【每當有handler新增到pipleline時,都會建立context,建立之後context和handler的關係永遠都不會變,因而可以快取context的引用】,如果事件從channel或者channelpipeline上觸發將沿整個pipeline傳播,但是context上的相同觸發方式只會傳遞給pipeline上的下一個能夠處理的handler
ChannelHandler是否可以在多個ChannelPipeline中複用?
在實現的handler上方使用註解@Sharable【注意ChannelHandler本身處理邏輯的執行緒安全性】,這樣多個pipeline就可以共享一個handler,這種方式可以用來收集跨多個channel的統計資訊