【Java进阶营】Java技术指南「序列化机制」采用protostuff和kryo高性能序列化框架实现RestTemplate的序列化组件

本文详细介绍了Java中的序列化机制,重点关注Kryo和protostuff这两种高性能序列化框架的实现。内容包括RedisConfiguration的配置、Kryo的序列化方式、支持的类型以及Kryo的线程安全问题。同时,文章还探讨了protostuff的序列化应用。通过实例展示了如何在Spring Boot应用中使用Kryo和protostuff作为RestTemplate的序列化组件。
摘要由CSDN通过智能技术生成

序列化

  • 序列化可以简单理解为对象–>字节的过程,同理,反序列化则是相反的过程。为什么需要序列化?因为网络传输只认字节。所以互信的过程依赖于序列化。

  • 网络传输的性能等诸多因素,通常会支持多种序列化方式以供使用者插拔使用,一些常用的序列化方案hessian,kryo,Protostuff、FST等,其中最快、效果最好的要数Kryo和Protostuff

RedisConfiguration的配置
  1. 创建Redis连接工厂对象(RedisConnectionFactory)

  2. 创建RestTemplate对象根据RedisConnectionFactory对象。

  3. 配置相关的RedisSerializaer组件

@Configuration
public class RedisConfiguration {

    @Bean("redisConnectionFactory")
    public RedisConnectionFactory redisConnectionFactory(RedisConfigMapper mapper) {
        List<RedisConfig> redisConfigs = mapper.getRedisConfig();
        List<String> clusterNodes = new ArrayList<>();
        for (RedisConfig rc : redisConfigs) {
            clusterNodes.add(rc.getUrl() + ":" + rc.getPort());
        }
        // 获取Redis集群配置信息
        RedisClusterConfiguration rcf = new RedisClusterConfiguration(clusterNodes);
        return new JedisConnectionFactory(rcf);
    }

    @Bean("redisTemplate")
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);
        // redis value使用的序列化器
        template.setValueSerializer(new XXXRedisSerializer<>());
        // redis key使用的序列化器
        template.setKeySerializer(new XXXRedisSerializer<>());
        template.setHashKeySerializer(new XXXRedisSerializer<>());
        template.setHashValueSerializer(new XXXRedisSerializer<>());
        template.afterPropertiesSet();
        return template;
    }
}

Kryo序列化实现

Maven配置文件
<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-autoconfigure</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>com.esotericsoftware</groupId>
            <artifactId>kryo</artifactId>
            <version>4.0.1</version>
        </dependency>
        <dependency>
            <groupId>de.javakaffee</groupId>
            <artifactId>kryo-serializers</artifactId>
            <version>0.41</version>
        </dependency>
        <dependency>
            <groupId>com.esotericsoftware</groupId>
            <artifactId>kryo-shaded</artifactId>
            <version>4.0.1</version>
        </dependency>
    </dependencies>

由于其底层依赖于ASM技术,与Spring等框架可能会发生ASM依赖的版本冲突(文档中表示这个冲突还挺容易出现)所以提供了另外一个依赖以供解决此问题:kryo-shaded

Kryo三种读写方式

如果知道class字节码,并且对象不为空

  kryo.writeObject(output, classObject);
  RestClass restClass = kryo.readObject(input, RestClass.class);

快速入门中的序列化/反序列化的方式便是这一种。而Kryo考虑到someObject可能为null,也会导致返回的结果为null,所以提供了第二套读写方式。在此我向大家推荐一个架构学习交流圈。交流学习指导伪鑫:1253431195(里面有大量的面试题及答案)里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

如果知道class字节码,并且对象可能为空

kryo.writeObjectOrNull(output, classObject);
RestClass someObject = kryo.readObjectOrNull(input, RestClass.class);

但这两种方法似乎都不能满足我们的需求,在RPC调用中,序列化和反序列化分布在不同的端点,对象的类型确定,我们不想依赖于手动指定参数,最好将字节码的信息直接存放到序列化结果中,在反序列化时自行读取字节码信息。Kryo考虑到了这一点,于是提供了第三种方式。如果实现类的字节码未知,并且对象可能为null。

  kryo.writeClassAndObject(output, object);
Object object = kryo.readClassAndObject(input);
if (object instanceof RestClass) {
}

我们牺牲了一些空间一些性能去存放字节码信息

支持的序列化类型

image

上面表格中支持的类型一览无余,这都是其默认支持的。

Kryo kryo = new Kryo();
kryo.addDefaultSerializer(RestClass.class, RestSerializer.class);

这样的方式,也可以为一个Kryo实例扩展序列化器

Kryo支持类型:
  • 枚举
  • 集合、数组
  • 子类/多态
  • 循环引用
  • 内部类
  • 泛型
Kryo反序列化的异常问题
  • Kryo不支持Bean中增删字段,如果使用Kryo序列化了一个类,存入了Redis,对类进行了修改,会导致反序列化的异常。

  • 另外需要注意的一点是使用反射创建的一些类序列化的支持。如使用Arrays.asList();创建的List对象,会引起序列化异常。

  • 不支持包含无参构造器类的反序列化,尝试反序列化一个不包含无参构造器的类将会得到以下的异常:

  • 保证每个类具有无参构造器是应当遵守的编程规范,但实际开发中一些第三库的相关类不包含无参构造࿰

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值