netty channel的線程安全性與@Sharable


 

1. Bootstrap中直接添加sb.childHandler(new MySimpleChannelInboundHandler())

這個childHandler都是同一個實例,也就說會導致不同的channel用了同一個handler

 

2. netty的一大好處就是每一個channel都有自己綁定的eventloop和channelHandler,這樣可以保證代碼串行執行,不必考慮並發同步的問題。

 

3. 只要寫個類繼承ChannelInitializer就行了,ChannelInitializer這個類比較特殊,你可以把它想象成是很多channelhandler的集合體,而且這個類就是@Shareable的,繼承了這個類之后你可以為每一個channel單獨創建handler,甚至是多個handler。

雖然所有的channel都共享了ChannelInitializerImpl這個實例,但是這個實例卻能為每一個channel new出新的handler實例,這就是區別。

 

https://www.fanyeong.com/2016/10/24/netty-channelhandler%E4%BD%BF%E7%94%A8%E6%8A%A5%E9%94%99/

 

4. 也並不是說ChannelInitializer就可以不用@Sharable了,要視具體情況而看,如果ChannelInitializer中還是同一個handler實例,就不行

https://blog.csdn.net/supper10090/article/details/78431948

 

5. 為了安全地被用於多個並發的Channel(即連接),sharable注解的ChannelHandler必須是線程安全的。

每一個新創建的Channel都將會被分配一個新的ChannelPipeline,但其中的handler未必是

https://www.jianshu.com/p/b241e3800fc0

 

6. 如果ChannelHandler被注解為 @Sharable,全局只有一個handler實例,它會被多個Channel的Pipeline共享,會被多線程並發調用,因此它不是線程安全的;如果存在跨ChannelHandler的實例級變量共享,需要特別注意,它可能不是線程安全的。

在整個ChannelPipeline執行過程中,可能會發生線程切換。此時,如果同一個對象在多個ChannelHandler中被共享,可能會被多線程並發操作

https://blog.csdn.net/y_xianjun/article/details/48341749

 

7. 總之,只應該在確定了你的 ChannelHandler 是線程安全的時才使用@Sharable 注解 

http://www.cnblogs.com/krcys/p/9297092.html

 

8. 新建一個Channel時會自動新建一個ChannelPipeline,也就是說他們之間是一對一的關系。另外需要注意的是:ChannelPipeline是線程安全的,也就是說,我們可以動態的添加、刪除其中的ChannelHandler。考慮這樣的場景:服務器需要對用戶登錄信息進行加密,而其他信息不加密,則可以首先將加密Handler添加到ChannelPipeline,驗證完用戶信息后,主動從ChnanelPipeline中刪除,從而實現該需求。

netty tcp(ws)鑒權2個方案 中即有一個鑒權后,remove from pipeline的案例

我的理解:channel屬於一個線程,ChannelPipeline屬於一個channel,所以對ChannelPipeline的操作始終在一個線程內

Sharable注解的使用是有限制的,多個ChannelPipeline共用一個handler實例,所以該Handler要求 無狀態。不能使用或改變本身的私有變量,因為ChannelHandler是 非線程安全的,使用私有變量會造成線程競爭而產生錯誤結果。


鏈接:https://www.jianshu.com/p/7dc5da98694c

 

9. 看書

channelpipeline 始終在一個線程操作

紅色框划重點

 

歸納就是:

(1)channel-1vs 1 pipeline-new handler

(2)channel-1vs 1 pipeline-common handler,需要@Sharable,且確保線程安全無成員變量

(3)channel始終在一個線程中,pipeline也是,但handler未必是

 

下面補充一個關於channel與線程的實踐  9.6

https://www.cnblogs.com/silyvin/articles/9599778.html

 

2019.12.17 補充

Sharable不僅是要開發者重視該handler需要是一個線程安全的,更重要的,應該是一個關於連接無狀態的,比如,對於拆包沾包handler,每個連接都應該有一個自己的對象,否則比如連接A-handlerA,連接B-handlerA,handlerA的確可以強行加鎖配置為線程安全的,事實上對於nio,只要設置,也能做到只有一個線程去調用HandlerA,縱使它是線程安全的,但它不是關於連接無狀態的,故不能在各連接復用一個這樣的Sharable的handler

對於netty粘包(一)消息定長 實踐,FixedLengthFrameDecoder不是連接無狀態的,而StringDecoder確是連接無狀態的,因為哪個連接都可以用一個公用的StringDecoder來反序列化字符串,只要將byte[]傳入;但拆包就不行,每個連接各自handler需要保存一個狀態-讀了多少字節,還要讀多少字節,應有各自的FrameDecoder,實踐位於:netty(十九)ChannelInitializer 使用公共handler

對於連接無關的,各連接就能共用一個handler對象,當然要用@Sharble注解


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM