NIO系列-4: 徹底搞明白Pipeline和Handler

我在51cto寫文章,只是爲了記錄自己的記憶,畢竟好記性不如爛筆頭。不是爲了博眼球,吸引粉絲。

這篇文章,我來講解下NIO裏的2個重要的概念:pipeline和handlers。

在設計模式裏面提到過一種責任鏈的模式,責任鏈模式簡單說就是擊鼓傳花,一個任務,順着鏈按個觸發。想詳細瞭解責任鏈模式的讀者,請自己百度,設計模式不在這篇文章討論範圍之內。

如果把數據比做水,那麼pipeline就是水管,水管上的閥門就是處理水的部分。比如一個Request請求進來,可能經過層層的處理;響應也是,所以類似這種服務端的框架很適合使用pipeline來解決。

wKioL1hbCcKAI3H9AAFAOi1SdUM886.png


其中的HandlerContext就是上面講的閥門,包括攔截器模式,Filter模式它們的實現都是類似的,全部是基於責任鏈的變體。每個HandlerContext都聚合一個Handler,由Handler負責具體的邏輯處理。

我們再來看下Netty中ChannelHandler的類圖:

wKiom1hbCgLyOc3fAAA80nOMfSc668.jpg

ChannelHandler有兩個子類ChannelInboundHandler和ChannelOutboundHandler,這兩個類對應了兩個數據流向,如果數據是從外部流入我們的應用程序,我們就看做是inbound,相反便是outbound。一個ChannelHandler處理完接收到的數據會傳給下一個Handler,或者什麼不處理,直接傳遞給下一個--責任鏈模式。

wKioL1hbCh6j6F9PAABPvXWKaVc644.jpg

上圖中我們可以看到,一個ChannelPipeline可以把兩種Handler(ChannelInboundHandler和ChannelOutboundHandler)混合在一起,當一個數據流進入ChannelPipeline時,它會從ChannelPipeline頭部開始傳給第一個ChannelInboundHandler,當第一個處理完後再傳給下一個,一直傳遞到管道的尾部。與之相對應的是,當數據被寫出時,它會從管道的尾部開始,先經過管道尾部的“最後”一個ChannelOutboundHandler,當它處理完成後會傳遞給前一個ChannelOutboundHandler。

這裏需要注意:

1)Netty中,可以註冊多個handler。ChannelInboundHandler按照註冊的先後順序執行;ChannelOutboundHandler按照註冊的先後順序逆序執行。

2)ChannelInboundHandler之間的傳遞,通過調用 ctx.fireChannelRead(msg) 實現;而調用ctx.write(msg) 將傳遞到ChannelOutboundHandler。ctx.write()方法執行後,需要調用flush()方法才能令它立即執行。

3)ChannelOutboundHandler 在註冊的時候需要放在最後一個ChannelInboundHandler之前,否則將無法傳遞到ChannelOutboundHandler。

InboundHandler和OutboundHandler在ChannelPipeline中是混合在一起的,那麼它們如何區分彼此呢?其實很容易,因爲它們各自實現的是不同的接口,對於inbound event,Netty會自動跳過OutboundHandler;相反若是outbound event,ChannelInboundHandler會被忽略掉。

最後,我們再來總結下幾個概念:

1)不管是server還是client,每個連接都會對應一個pipeline,該pipeline在Channel被創建的時候創建。

2)ChannelPipeline是ChannelHandler的容器,它包含了一個ChannelHander形成的列表,且所有ChannelHandler都會註冊到ChannelPipeline中。其中ChannelHander用於處理連接的Inbound或者Outbound事件。

3)ChannelPipeline,它維護了一個有序的ChannelHandler列表,但並非是直接關聯,而是通過維護ChannelHandlerContext進行關聯。

4)一個ChannelHandlerContext只能對應一個ChannelHander,只對應一個Channel;而一個ChannelHander則可以對應多個ChannelHandlerContext。


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