• 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。

  • 相关阅读:
    openpyxl处理excel
    python播放声音
    python利用wave对声音数据进行处理
    线性代数相关知识
    《深度学习》笔记-卷积神经网络
    Django--知识补充
    Django--2、form表单
    Django--4、认证系统
    Django--1、MTV及基本应用
    前端--3、jQuery
  • 原文地址:https://www.cnblogs.com/shamo89/p/8601009.html
Copyright © 2020-2023  润新知