资讯专栏INFORMATION COLUMN

dubbo源码解析(四十二)序列化——开篇

keke / 2583人阅读

摘要:在版本中,支持五种序列化方式,分别是依赖阿里的库,功能强大支持普通类包括任意或完全兼容序列化协议的系列化框架,序列化速度大概是的倍,大小是大小的左右。但这里实际不是原生的序列化,而是阿里修改过的,它是默认启用的序列化方式自带的序列化实现。

序列化——开篇
目标:介绍dubbo中序列化的内容,对dubbo中支持的序列化方式做对比,介绍dubbo-serialization-api下的源码
前言

序列化就是将对象转成字节流,用于网络传输,以及将字节流转为对象,用于在收到字节流数据后还原成对象。序列化的好处我就不多说了,无非就是安全性更好、可跨平台等。网上有很多总结的很好,我在这里主要讲讲dubbo中序列化的设计和实现了哪些序列化方式。

dubbo在2.6.x版本中,支持五种序列化方式,分别是

fastjson:依赖阿里的fastjson库,功能强大(支持普通JDK类包括任意Java Bean Class、Collection、Map、Date或enum)

fst:完全兼容JDK序列化协议的系列化框架,序列化速度大概是JDK的4-10倍,大小是JDK大小的1/3左右。

hessian2:hessian是一种跨语言的高效二进制序列化方式。但这里实际不是原生的hessian2序列化,而是阿里修改过的hessian lite,它是dubbo RPC默认启用的序列化方式

jdk:JDK自带的Java序列化实现。

kryo:是一个快速序列化/反序列化工具,其使用了字节码生成机制(底层依赖了 ASM 库),因此具有比较好的运行速度,速度快,序列化后体积小,跨语言支持较复杂

在dubbo最新的2.7.0版本中支持了protostuff,之前的版本dubbo还实现了自己的dubbo序列化,但是由于还不够成熟,所有暂时移除了dubbo序列化的实现。

从性能上对比,fst和kryo>hessian2>fastjson>jdk。

他们具体的实现我不讲解,因为很多都直接使用了对应的依赖裤,我只讲解dubbo序列化的接口设计。

源码分析 (一)DataInput
public interface DataInput {

    /**
     * Read boolean.
     * 读取布尔类型
     * @return boolean.
     * @throws IOException
     */
    boolean readBool() throws IOException;

    /**
     * Read byte.
     * 读取字节
     * @return byte value.
     * @throws IOException
     */
    byte readByte() throws IOException;

    /**
     * Read short integer.
     * 读取short类型
     * @return short.
     * @throws IOException
     */
    short readShort() throws IOException;

    /**
     * Read integer.
     * 读取integer类型
     * @return integer.
     * @throws IOException
     */
    int readInt() throws IOException;

    /**
     * Read long.
     * 读取long类型
     * @return long.
     * @throws IOException
     */
    long readLong() throws IOException;

    /**
     * Read float.
     * 读取float类型
     * @return float.
     * @throws IOException
     */
    float readFloat() throws IOException;

    /**
     * Read double.
     * 读取double类型
     * @return double.
     * @throws IOException
     */
    double readDouble() throws IOException;

    /**
     * Read UTF-8 string.
     * 读取UTF-8 string
     * @return string.
     * @throws IOException
     */
    String readUTF() throws IOException;

    /**
     * Read byte array.
     * 读取byte数组
     * @return byte array.
     * @throws IOException
     */
    byte[] readBytes() throws IOException;
}

该接口是数据输入接口,可以看到定义了从 InputStream 中各类数据类型的读取方法。

(二)DataOutput
public interface DataOutput {

    /**
     * Write boolean.
     * 输出boolean类型
     * @param v value.
     * @throws IOException
     */
    void writeBool(boolean v) throws IOException;

    /**
     * Write byte.
     * 输出byte类型
     * @param v value.
     * @throws IOException
     */
    void writeByte(byte v) throws IOException;

    /**
     * Write short.
     * 输出short类型
     * @param v value.
     * @throws IOException
     */
    void writeShort(short v) throws IOException;

    /**
     * Write integer.
     * 输出integer类型
     * @param v value.
     * @throws IOException
     */
    void writeInt(int v) throws IOException;

    /**
     * Write long.
     * 输出long类型
     * @param v value.
     * @throws IOException
     */
    void writeLong(long v) throws IOException;

    /**
     * Write float.
     * 输出float类型
     * @param v value.
     * @throws IOException
     */
    void writeFloat(float v) throws IOException;

    /**
     * Write double.
     * 输出double类型
     * @param v value.
     * @throws IOException
     */
    void writeDouble(double v) throws IOException;

    /**
     * Write string.
     * 输出string类型
     * @param v value.
     * @throws IOException
     */
    void writeUTF(String v) throws IOException;

    /**
     * Write byte array.
     * 输出byte数组
     * @param v value.
     * @throws IOException
     */
    void writeBytes(byte[] v) throws IOException;

    /**
     * Write byte array.
     * 输出byte数组中部分数据
     * @param v   value.
     * @param off offset.
     * @param len length.
     * @throws IOException
     */
    void writeBytes(byte[] v, int off, int len) throws IOException;

    /**
     * Flush buffer.
     * 刷新缓冲区
     * @throws IOException
     */
    void flushBuffer() throws IOException;
}

该接口是数据输出接口,可以看到定义了向 InputStream 中,写入基本类型的数据。

(三)ObjectOutput
public interface ObjectOutput extends DataOutput {

    /**
     * write object.
     * 输入object类型
     * @param obj object.
     */
    void writeObject(Object obj) throws IOException;

}

在 DataOutput 的基础上,增加写入object类型的数据。

(四)ObjectInput
public interface ObjectInput extends DataInput {

    /**
     * read object.
     * 读取object类型数据
     * @return object.
     */
    Object readObject() throws IOException, ClassNotFoundException;

    /**
     * read object.
     * 根据class类型读取object类型数据
     * @param cls object type.
     * @return object.
     */
     T readObject(Class cls) throws IOException, ClassNotFoundException;

    /**
     * read object.
     * 取object类型数据
     * @param cls object type.
     * @return object.
     */
     T readObject(Class cls, Type type) throws IOException, ClassNotFoundException;

}

该接口是继承了DataInput 接口,在 DataInput 的基础上,增加读取object类型的数据。

(五)Cleanable
public interface Cleanable {

    /**
     * 清理
     */
    void cleanup();
}

该接口是清理接口,定义了一个清理方法。目前只有kryo实现的时候,完成序列化或反序列化,需要做清理。通过实现该接口,执行清理的逻辑。

(六)Serialization
@SPI("hessian2")
public interface Serialization {

    /**
     * get content type id
     * 获得内容类型编号
     * @return content type id
     */
    byte getContentTypeId();

    /**
     * get content type
     * 获得内容类型名
     * @return content type
     */
    String getContentType();

    /**
     * create serializer
     * 创建 ObjectOutput 对象,序列化输出到 OutputStream
     * @param url
     * @param output
     * @return serializer
     * @throws IOException
     */
    @Adaptive
    ObjectOutput serialize(URL url, OutputStream output) throws IOException;

    /**
     * create deserializer
     * 创建 ObjectInput 对象,从 InputStream 反序列化
     * @param url
     * @param input
     * @return deserializer
     * @throws IOException
     */
    @Adaptive
    ObjectInput deserialize(URL url, InputStream input) throws IOException;

}

该接口是序列化接口,该接口也是可扩展接口,默认是使用hessian2序列化方式。其中定义了序列化和反序列化等方法

(七)SerializableClassRegistry
public abstract class SerializableClassRegistry {

    /**
     * 可序列化类类的集合
     */
    private static final Set registrations = new LinkedHashSet();

    /**
     * only supposed to be called at startup time
     * 把可序列化的类加入到集合
     */
    public static void registerClass(Class clazz) {
        registrations.add(clazz);
    }

    /**
     * 获得可序列化的类的集合
     * @return
     */
    public static Set getRegisteredClasses() {
        return registrations;
    }
}

该类提供一个序列化统一的注册中心,其实就是封装了可序列化类的集合

(八)SerializationOptimizer
public interface SerializationOptimizer {

    /**
     * 需要序列化的类的集合
     * @return
     */
    Collection getSerializableClasses();
}

该接口序列化优化器接口,在 Kryo 、FST 中,支持配置需要优化的类。业务系统中,可以实现自定义的 SerializationOptimizer,进行配置。或者使用文件来配置也是一个选择。

后记
该部分相关的源码解析地址:https://github.com/CrazyHZM/i...

该文章讲解了dubbo支持的几种序列化方式,介绍了序列化的接口设计,具体的实现我不再讲述,因为大部分都是调用了不同的依赖库。接下来我会说一个分割线,我讲开始讲解2.7.x版本的新特性,然后分析新特性的实现,下一篇就先讲解一下dubbo2.7.0的大改动。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/73692.html

相关文章

  • dubbo源码解析四十六)消费端发送请求过程

    摘要:可以参考源码解析二十四远程调用协议的八。十六的该类也是用了适配器模式,该类主要的作用就是增加了心跳功能,可以参考源码解析十远程通信层的四。二十的可以参考源码解析十七远程通信的一。 2.7大揭秘——消费端发送请求过程 目标:从源码的角度分析一个服务方法调用经历怎么样的磨难以后到达服务端。 前言 前一篇文章讲到的是引用服务的过程,引用服务无非就是创建出一个代理。供消费者调用服务的相关方法。...

    fish 评论0 收藏0
  • dubbo源码解析四十八)异步化改造

    摘要:大揭秘异步化改造目标从源码的角度分析的新特性中对于异步化的改造原理。看源码解析四十六消费端发送请求过程讲到的十四的,在以前的逻辑会直接在方法中根据配置区分同步异步单向调用。改为关于可以参考源码解析十远程通信层的六。 2.7大揭秘——异步化改造 目标:从源码的角度分析2.7的新特性中对于异步化的改造原理。 前言 dubbo中提供了很多类型的协议,关于协议的系列可以查看下面的文章: du...

    lijinke666 评论0 收藏0
  • dubbo源码解析四十七)服务端处理请求过程

    摘要:而存在的意义就是保证请求或响应对象可在线程池中被解码,解码完成后,就会分发到的。 2.7大揭秘——服务端处理请求过程 目标:从源码的角度分析服务端接收到请求后的一系列操作,最终把客户端需要的值返回。 前言 上一篇讲到了消费端发送请求的过程,该篇就要将服务端处理请求的过程。也就是当服务端收到请求数据包后的一系列处理以及如何返回最终结果。我们也知道消费端在发送请求的时候已经做了编码,所以我...

    yzzz 评论0 收藏0
  • dubbo源码解析四十三)2.7新特性

    摘要:大揭秘目标了解的新特性,以及版本升级的引导。四元数据改造我们知道以前的版本只有注册中心,注册中心的有数十个的键值对,包含了一个服务所有的元数据。 DUBBO——2.7大揭秘 目标:了解2.7的新特性,以及版本升级的引导。 前言 我们知道Dubbo在2011年开源,停止更新了一段时间。在2017 年 9 月 7 日,Dubbo 悄悄的在 GitHub 发布了 2.5.4 版本。随后,版本...

    qqlcbb 评论0 收藏0
  • dubbo源码解析(十九)远程调用——开篇

    摘要:远程调用开篇目标介绍之后解读远程调用模块的内容如何编排介绍中的包结构设计以及最外层的的源码解析。十该类就是远程调用的上下文,贯穿着整个调用,例如调用,然后调用。十五该类是系统上下文,仅供内部使用。 远程调用——开篇 目标:介绍之后解读远程调用模块的内容如何编排、介绍dubbo-rpc-api中的包结构设计以及最外层的的源码解析。 前言 最近我面临着一个选择,因为dubbo 2.7.0-...

    jayce 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<