文档章节

Dubbo 源码解读 —— 可支持序列化及自定义扩展

Ryan-瑞恩
 Ryan-瑞恩
发布于 07/16 18:26
字数 1426
阅读 192
收藏 6

一、概述

​ 从源码中,我们可以看出来。目前,Dubbo 内部提供了 5 种序列化的方式,分别为 fastjson、Hessian2、Kryo、fst 及 Java原生支持的方式 。

​ 针对不同的序列化方式,对比内容如下:

名称 优点 缺点
Hessian 性能较好,多语言支持(推荐使用) Hessian的各版本兼容性不好,可能和应用使用的Hessian冲突,Dubbo内嵌了hessian3.2.1的源码
fastjson 纯文本,可跨语言解析,缺省采用FastJson解析 性能较差
kryo 速度快,序列化后体积小 跨语言支持较复杂
fst 兼容JDK序列化协议;序列化速度快;体积小;  
jdk Java原生支持;无需引入第三方类库; 性能较差

​ 从成熟度上来说,Hessian 和 Java 相对成熟一些,可用于生产环境。

二、Dubbo serialization 实现

​ 整体的代码结构比较清晰,按照不同类型的序列化方式,划分成了多个子模块。根据模块的名称,想必你也能够知道该模块是什么序列化方式。接下来,我们一一进行解读:

2.1 API 模块

​ 他们的依赖关系如 UML 图库直接看出来,DataInput 和 DataOutput 接口类,主要是针对基本类型数据进行序列化和反序列化。ObjectInput 和 ObjectOutput 分别继承 DataInput 和 DataOutput,主要是针对对象类型序列化和反序列化。

​ 抽象类 SerializableClassRegistry 主要是提供一个序列化统一的注册中心。该类只有两个方法:registerClass 和 getRegisteredClasses,前者是在系统进行初始化时,对可支持序列化方式的一个注册功能,实际上就是将可序列化类(Class)加入到 Set 集合中!后者,主要是返回又有的注册序列化 Class 类。

​ Serialization 接口主要提供了四个方法:

 byte getContentTypeId() # 获取 contextType 编号ID 
 String getContentType() # 获取 contextType 类型(kyro 的为: "x-application/kryo") 
 ObjectOutput serialize(URL url, OutputStream output) # 根据输入流信息,构造序列化对象 
 ObjectInput deserialize(URL url, InputStream input) # 根据输出流信息,构造反序列化对象

​ 实现代码相对简单,读者可自行查阅。

2.2 API 模块

​ 在这里,笔者主要以 Kyro 模块为主来解读,其他模块雷同,不再重述!

KryoSerialization 类实现了  Serialization 接口,并实现了其中的方法。 在  serialize() 方法中,创建了 Kryo 的 序列化类对象,在 deserialize() 方法中,创建了 KryoObjectInput 反序列化类对象。

    在参数中,传递有  URL url 目前这个参数没有用到,暂不作过多解读说明。
接下来看看 KryoSerialization 实现类:

public class KryoSerialization implements Serialization {

    @Override
    public byte getContentTypeId() {
        return 8;
    }

    @Override
    public String getContentType() {
        return "x-application/kryo";
    }

    @Override
    public ObjectOutput serialize(URL url, OutputStream out) throws IOException {
        return new KryoObjectOutput(out);
    }

    @Override
    public ObjectInput deserialize(URL url, InputStream is) throws IOException {
        return new KryoObjectInput(is);
    }
}
我们先来看看 KryoObjectOutput 类的实现。

在构造 KryoObjectOutput 传入 了 outputStream 对象,初始化了 Kryo 的 Output 类实例, (如下,省略了部分代码),并通过 KryoUtils 获取 Kryo 对象。
public class KryoObjectOutput implements ObjectOutput, Cleanable {

    private Output output;
    private Kryo kryo;

    public KryoObjectOutput(OutputStream outputStream) {
        output = new Output(outputStream);
        this.kryo = KryoUtils.get();
    }

    @Override
    public void writeBool(boolean v) throws IOException {
        output.writeBoolean(v);
    }

    ........

    @Override
    public void cleanup() {
        KryoUtils.release(kryo);
        kryo = null;
    }
}

接下来,进入到 KryoUtils 中,看看 Kryo 是如何来构造出来的。

public class KryoUtils {
    private static AbstractKryoFactory kryoFactory = new ThreadLocalKryoFactory();

    public static Kryo get() {
        return kryoFactory.getKryo();
    }

    public static void release(Kryo kryo) {
        kryoFactory.returnKryo(kryo);
    }

    public static void register(Class<?> clazz) {
        kryoFactory.registerClass(clazz);
    }

    public static void setRegistrationRequired(boolean registrationRequired) {
        kryoFactory.setRegistrationRequired(registrationRequired);
    }
}

该工具类中,还提供了 register 和 setRegistrationRequired 类,以支持动态注册功能。

这里有有一个设计模式的使用,是“抽象工厂模式”,一共有上个继承类,分别是:PrototypeKryoFactory、PooledKryoFactory、ThreadLocalKryoFactory。 这里我们以  ThreadLocalKryoFactory 作为主要的入口来解读,其他两个工厂类相对简单一些。
    ![](https://oscimg.oschina.net/oscnet/f839bb21e0b44db1f2fadd1b04e0a309afb.jpg)

Kryo 的主要产生是通过 ThreadLocalKryoFactory 中的ThreadLocal 来实际进行的实例化,并且该类继承了 AbstractKryoFactor 工厂类。当调用该工厂类的 getKryo() 方法时, holder 调用了其 get 方法,进行调用了ThreadLocal 内部的 initialValue() 方法,进而调用父类的 create() 方法,并开始了真正的初始化工作。

public class ThreadLocalKryoFactory extends AbstractKryoFactory {

    private final ThreadLocal<Kryo> holder = new ThreadLocal<Kryo>() {
        @Override
        protected Kryo initialValue() {
            return create();
        }
    };

    @Override
    public void returnKryo(Kryo kryo) {
        // do nothing
    }

    @Override
    public Kryo getKryo() {
        return holder.get();
    }
}

初始化的细节信息,读者可自行在其抽象类中查阅。代码相对简单!

三、自定义扩展

目前,dubbo 是没有支持 Google protocol buffer 序列化方式。用户可按照 Dubbo 源码接口及规范来实现。

首先,需要实现 API 模块中的 Serialization 类,分别实现 ObjectInput 和 ObjectOut 接口。在实现类中编写序列化及反序列化代码。

最后,需要手动在 classpath 下创建 META-INF/dubbo/internel/org.apache.dubbo.common.serialize.Serialization 路径。 文件名称为:

org.apache.dubbo.common.serialize.Serialization。在该文件中写入自己的实现类,及该实现的 schema。例如:

protobuf=org.apache.dubbo.common.serialize.protocol.ProtobufSerialization

将自己的实现打包,注意打包的时候,一定要将 /META-INF 文件夹下的所有内容都打包进去。否则,将不会被 classloader 加载到,进而报错!

四、总结

  1. 在 API 模块中,将不同的处理划分为接口,针对接口编程,如:DataInput 和 DataOuput 接口分开,单一职责;
  2. 在 Kryo 的实现中,采用了抽象工厂模式;

=============================================================================

本文就到这里,由于本人水平有限,若有解读错误之处,欢迎随时拍砖。

© 著作权归作者所有

共有 人打赏支持
Ryan-瑞恩

Ryan-瑞恩

粉丝 146
博文 226
码字总数 176302
作品 0
西安
后端工程师
Dubbo 实现原理与源码解析系列 —— 精品合集

摘要: 原创出处 http://www.iocoder.cn/Dubbo/good-collection/ 「芋道源码」欢迎转载,保留摘要,谢谢! 1.【芋艿】精尽 Dubbo 原理与源码专栏 2.【老徐】RPC 专栏 3.【肥朝】Dubbo 源码解析...

芋道源码掘金Java群217878901
06/23
0
0
dubbo序列化过程源码分析:

先看下dubbo在serialize层的类设计方案 序列化方案的入口,是接口Serialization的实现类。 目前dubbo的spi实现有: 具体看下DubboSerialization类和Hessian2Serialization类: 可以看到具体序...

wannshan
02/02
5
0
Dubbo分析之Serialize层

Dubbo整体设计 关于Dubbo的整体设计可以查看官方文档,下图可以清晰的表达Dubbo的整体设计: 1.图例说明 图中左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口...

ksfzhaohui
10/09
0
2
dubbo通信消息解析过程分析(1)

由于rpc底层涉及网络编程接口,线程模型,网络数据结构,服务协议,细到字节的处理。牵涉内容较多,今天就先从一个点说起。 说说,dubbo通过netty框架做传输层,从接到数据字节流到把字节转换...

wannshan
01/19
5
0
Dubbo 源码解读——自定义 Classloader 之 ExtensionLoader

众所周知,Dubbo 是阿里巴巴公司自主研发开源的一个高性能的服务框架(现已捐献给 Apache 基金会组织),应用之间可以通过 RPC 的方式来互相调用并返回结果。主要基于 Java 语言开发,它提供...

Ryan-瑞恩
07/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

idea 通过jpa自动生成实体类

引入jpa包 打开persistence窗口 右键选择连接数据库 如果数据库没配置,则可以在下图选项中配置 选择好数据库和实体类的生成地址

斩神魂
27分钟前
1
0
tcpdump 命令

TCPDUMP简介 tcpdump 是一个很常用的网络包分析工具,可以用来显示通过网络传输到本系统的 TCP/IP 以及其他网络的数据包。tcpdump 使用 libpcap 库来抓取网络报,这个库在几乎在所有的 Linu...

寰宇01
34分钟前
2
0
软件的Alpha、Beta、RC、GA版本的区别

Alpha:是内部测试版,一般不向外部发布,会有很多Bug.一般只有测试人员使用。 Beta:也是测试版,这个阶段的版本会一直加入新的功能。在Alpha版之后推出。 RC:(Release Candidate) 顾名思义...

乔老哥
35分钟前
2
0
慢雾安全海贼王:从DApp亡灵军团,细说区块链安全

本文转载自微信公号“万向区块链”,为慢雾安全负责人海贼王在万向区块链实验室举办的2018上海区块链国际周-技术开放日上的演讲速记整理。 这张图总结了智能合约攻防的各个方面,分为两大部分...

万向区块链
41分钟前
13
0
Matlab编程之——卷积神经网络CNN代码解析

卷积神经网络CNN代码解析 deepLearnToolbox-master是一个深度学习matlab包,里面含有很多机器学习算法,如卷积神经网络CNN,深度信念网络DBN,自动编码AutoE ncoder(堆栈SAE,卷积CAE)的作...

酒逢知己千杯少
42分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部