Netty @Sharable的使用
一、@Sharable的真實含義
如果你添加的不是單例Handler,你加不加@Sharable沒有任何區(qū)別
如果你添加的是單例Handler,只要它會被添加到多個channel的pipeline,那就必須加上@Sharable
- 一般情況下,我們的代碼是這樣:
在initChannel方法中,我們addLast傳入的Handler實例,他是不是單例的與netty沒有任何關(guān)系,和你是否注解@Sharable也沒有任何關(guān)系。就拿上面的代碼說,它就不是單例的,每次都是new一個新對象,這時候你ShareTestChannelHandler這個類加不加@Sharable沒有任何區(qū)別。
- 如下代碼
如果,你傳入一個單例的Handler對象,只要它會被添加到多個channel的pipeline鏈中,那它就必須是@Sharable的,不然就拋出第1點(diǎn)說的異常
二、是不是所有Handler都可以加上@Sharable
但是,如果我們明確知道MessageCodec是線程安全的),要使用@Sharable,就不要繼承ByteToMessageCodec了,可以通過繼承 MessageToMessageCodec來實現(xiàn)。
@Slf4j @ChannelHandler.Sharable /*** 必須和 LengthFieldBasedFrameDecoder 一起使用,以確保接到的 ByteBuf 消息是完整的,防止沒接收到完整信息,又切換到其他channel使用,導(dǎo)致線程不安全*/ public class MessageCodecSharable extends MessageToMessageCodec<ByteBuf, Message> {@Overridepublic void encode(ChannelHandlerContext ctx, Message msg, List<Object> outList) throws Exception {ByteBuf out = ctx.alloc().buffer();// 1. 4 字節(jié)的魔數(shù)out.writeBytes(new byte[]{1, 2, 3, 4});// 2. 1 字節(jié)的版本,out.writeByte(1);// 3. 1 字節(jié)的序列化方式 jdk 0 , json 1out.writeByte(Config.getSerializerAlgorithm().ordinal());// 4. 1 字節(jié)的指令類型out.writeByte(msg.getMessageType());// 5. 4 個字節(jié)out.writeInt(msg.getSequenceId());// 無意義,對齊填充out.writeByte(0xff);// 6. 獲取內(nèi)容的字節(jié)數(shù)組byte[] bytes = Config.getSerializerAlgorithm().serialize(msg);// 7. 長度out.writeInt(bytes.length);// 8. 寫入內(nèi)容out.writeBytes(bytes);outList.add(out);}@Overrideprotected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {int magicNum = in.readInt();byte version = in.readByte();byte serializerAlgorithm = in.readByte(); // 0 或 1byte messageType = in.readByte(); // 0,1,2...int sequenceId = in.readInt();in.readByte();int length = in.readInt();byte[] bytes = new byte[length];in.readBytes(bytes, 0, length);// 找到反序列化算法Serializer.Algorithm algorithm = Serializer.Algorithm.values()[serializerAlgorithm];// 確定具體消息類型Class<? extends Message> messageClass = Message.getMessageClass(messageType);Message message = algorithm.deserialize(messageClass, bytes);out.add(message);} }三、總結(jié)
加了@Sharable的類,netty就認(rèn)為是線程安全,可以共享,而只要netty明確的禁止了使用單例Handler,即使你給他加上@Sharable,也會被禁止掉。同時,如果一個類是單例的Handler對象,同時他會被添加到多個channel的pipeline鏈中,那它就必須是@Sharable的,不然也會報錯。
- handler 不保存狀態(tài)時,就可以安全地在多線程下被共享
- 但要注意對于編解碼器類,不能繼承 ByteToMessageCodec 或 CombinedChannelDuplexHandler 父類,他們的構(gòu)造方法對 @Sharable 有限制
- 如果能確保編解碼器不會保存狀態(tài),可以繼承 MessageToMessageCodec 父類
參考視頻
參考文章
參考文章
總結(jié)
以上是生活随笔為你收集整理的Netty @Sharable的使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Netty自定义协议
- 下一篇: springboot @JsonSeri