Netty(五):Netty中如何序列化數據


JDK提供了ObjectOutputStream和ObjectInputStream,用於通過網絡對POJO的基本數據類型和圖進行序列化和反序列化。該API並不復雜,而且可以被應用於任何實現了java.io.Serializable接口的對象。但是它的性能也不是非常高效的。在這一節中,我們將看到Netty必須為此提供什么。

一、JDK序列化

如果你的應用程序必須要和使用了ObjectOutputStream和ObjectInputStream的遠程節點交互,並且兼容性也是你最關心的,那么JDK序列化將是正確的選擇。下表列出了Netty提供的用於和JDK進行互操作的序列化類。

JDK序列化編解碼器

CompatibleObjectDecoder和使用JDK序列化的非基於Netty的遠程節點進行互操作的解碼器
CompatibleObjectEncoder 和使用JDK序列化的非基於Netty的遠程節點進行互操作的編碼器
ObjectDecoder 構建於JDK 序列化之上的使用自定義的序列化來解碼的解碼器;當沒有其他的外部依賴時,它提供了速度上的改進。否則其他的序列化實現更加可取
ObjectEncoder 構建於JDK 序列化之上的使用自定義的序列化來編碼的編碼器;當沒有其他的外部依賴時,它提供了速度上的改進。否則其他的序列化實現更加可取

二、使用JBoss Marshalling 進行序列化

如果你可以自由地使用外部依賴,那么JBossMarshalling將是個理想的選擇:它比JDK序列化最多快3倍,而且也更加緊湊。在JBossMarshalling官方網站主頁上的概述中對它是這么定義的:

JBoss Marshalling是一種可選的序列化API,它修復了在JDK序列化API中所發現的許多問題,同時保留了與java.io.Serializable及其相關類的兼容性,並添加了幾個新的可調優參數以及額外的特性,所有的這些都是可以通過工廠配置(如外部序列化器、類/實例查找表、類解析以及對象替換等)實現可插拔的。

Netty通過下表所示的兩組解碼器/編碼器對為Boss Marshalling 提供了支持。第一組兼容只使用JDK序列化的遠程節點。第二組提供了最大的性能,適用於和使用JBoss Marshalling的遠程節點一起使用。

JBoss Marshalling 編解碼器

CompatibleMarshallingDecoder 與只使用JDK 序列化的遠程節點兼容
MarshallingDecoder 適用於使用JBoss Marshalling 的節點。這些類必須一起使用。

以下代碼清單展示了如何使用MarshallingDecoder 和MarshallingEncoder。同樣,幾乎只是適當地配置ChannelPipeline罷了。

使用JBoss Marshalling

public class MarshallingInitializer extends ChannelInitializer<Channel> {
    private final MarshallerProvider marshallerProvider;
    private final UnmarshallerProvider unmarshallerProvider;

    public MarshallingInitializer(UnmarshallerProvider unmarshallerProvider,
            MarshallerProvider marshallerProvider) {
        this.marshallerProvider = marshallerProvider;
        this.unmarshallerProvider = unmarshallerProvider;
    }

    @Override
    protected void initChannel(Channel channel) throws Exception {
        ChannelPipeline pipeline = channel.pipeline();
        pipeline.addLast(new MarshallingDecoder(unmarshallerProvider));// 添加MarshallingDecoder以將ByteBuf 轉換為POJO
        pipeline.addLast(new MarshallingEncoder(marshallerProvider));// 添加MarshallingEncoder 以將POJO轉換為ByteBuf
        pipeline.addLast(new ObjectHandler());// 添加ObjectHandler,以處理普通的實現了Serializable 接口的POJO
    }

    public static final class ObjectHandler extends SimpleChannelInboundHandler<Serializable> {
        @Override
        public void channelRead0(ChannelHandlerContext channelHandlerContext, Serializable serializable)
                throws Exception {
            // Do something
        }
    }
}

三、通過Protocol Buffers 序列化

Netty序列化的最后一個解決方案是利用Protocol Buffers的編解碼器,它是一種由Google公司開發的、現在已經開源的數據交換格式。可以在https://github.com/google/protobuf找到源代碼。
Protocol Buffers 以一種緊湊而高效的方式對結構化的數據進行編碼以及解碼。它具有許多的編程語言綁定,使得它很適合跨語言的項目。表11-10 展示了Netty為支持protobuf 所提供的ChannelHandler實現。

Protobuf 編解碼器

ProtobufDecoder 使用protobuf對消息進行解碼
ProtobufEncoder 使用protobuf對消息進行編碼
ProtobufVarint32FrameDecoder 根據消息中的Google Protocol Buffers 的“Base 128 Varints整型長度字段值動態地分割所接收到的ByteBuf
ProtobufVarint32LengthFieldPrepender 向ByteBuf 前追加一個Google Protocal Buffers 的“Base128 Varints”整型的長度字段值

在這里我們又看到了,使用protobuf只不過是將正確的ChannelHandler添加到ChannelPipeline 中,如下代碼所示。

使用protobuf

public class ProtoBufInitializer extends ChannelInitializer<Channel> {
        private final MessageLite lite;

        public ProtoBufInitializer(MessageLite lite) {
            this.lite = lite;
        }

        @Override
        protected void initChannel(Channel ch) throws Exception {
          ChannelPipeline pipeline = ch.pipeline();
          pipeline.addLast(new ProtobufVarint32FrameDecoder());// 添加ProtobufVarint32FrameDecoder以分隔幀
          pipeline.addLast(new ProtobufEncoder()); // 添加ProtobufEncoder以處理消息的編碼
          pipeline.addLast(new ProtobufDecoder(lite));// 添加ProtobufDecoder以解碼消息
          pipeline.addLast(new ObjectHandler());// 添加ObjectHandler以處理解碼消息
        }

        public static final class ObjectHandler extends SimpleChannelInboundHandler<Object> {
            @Override
            public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
                // Do something with the object
            }
        }
    }

由Netty專門的解碼器和編碼器所支持的不同的序列化選項:標准JDK序列化、JBoss Marshalling以及Google的Protocol Buffers。


免責聲明!

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



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