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的操作始終在一個線程內
鏈接: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注解