RPC 框架需要通过网络通信实现跨 JVM 的调用。既然需要网络通信,那就必然会使用到序列化与反序列化的相关技术,Dubbo 也不例外。
1 JDK序列化操作
1.1 实现 Serializable 接口
被序列化对象实现 Serializable 接口。
public class Student implements Serializable { private static final long serialVersionUID = 1L; private String name; private int age; private transient StudentUtil studentUtil; }
- transient 关键字的作用
在对象序列化过程中忽略被其修饰的成员属性变量。可用来修饰一些非数据型的字段以及一些可以通过其他字段计算得到的值。合理使用 transient,可降低序列化后的数据量,提高网络传输效率。
1.2 生成 serialVersionUID
生成一个序列号 serialVersionUID。该序列号非必需,但推荐生成。serialVersionUID 字面含义是序列化的版本号,只有序列化和反序列化的 serialVersionUID 都相同的情况下,才能够成功地反序列化。若类中没有定义 serialVersionUID,那么 JDK 也会随机生成一个 serialVersionUID。如果在某些场景中,你希望不同版本的类序列化和反序列化相互兼容,那就需要定义相同的 serialVersionUID。
1.3 重写 writeObject()/readObject()
根据需求决定是否要重写 writeObject()/readObject() 方法,实现自定义序列化。
1.4 调用writeObject()/readObject()
调用 java.io.ObjectOutputStream 的 writeObject()/readObject() 进行序列化与反序列化。
Java 本身的序列化操作简单,但第三方序列化框架的速度更快、序列化的效率更高,而且支持跨语言操作。
2 常见序列化算法
Apache Avro
与编程语言无关的序列化格式。Avro 依赖于用户自定义的 Schema,在进行序列化数据的时候,无须多余的开销,就可以快速完成序列化,并且生成的序列化数据也较小。当进行反序列化的时候,需要获取到写入数据时用到的 Schema。在 Kafka、Hadoop 以及 Dubbo 中都可以使用 Avro 作为序列化方案。
FastJson
阿里开源的 JSON 解析库,可以解析 JSON 格式的字符串。它支持将 Java 对象序列化为 JSON 字符串,反过来从 JSON 字符串也可以反序列化为 Java 对象。FastJson 是 Java 程序员常用到的类库之一,正如其名,“快”是其主要卖点。从官方的测试结果来看,FastJson 确实是最快的,比 Jackson 快 20% 左右,但是近几年 FastJson 的安全漏洞比较多,所以你在选择版本的时候,还是需要谨慎一些。
Fst(全称是 fast-serialization)
高性能 Java 对象序列化工具包,100% 兼容 JDK 原生环境,序列化速度大概是JDK 原生序列化的 4~10 倍,序列化后的数据大小是 JDK 原生序列化大小的 1/3 左右。目前,Fst 已经更新到 3.x 版本,支持 JDK 14。
Kryo
高效的 Java 序列化/反序列化库,目前 Twitter、Yahoo、Apache 等都在使用该序列化技术,特别是 Spark、Hive 等大数据领域用得较多。Kryo 提供了一套快速、高效和易用的序列化 API。无论是数据库存储,还是网络传输,都可以使用 Kryo 完成 Java 对象的序列化。Kryo 还可以执行自动深拷贝和浅拷贝,支持环形引用。Kryo 的特点是 API 代码简单,序列化速度快,并且序列化之后得到的数据比较小。另外,Kryo 还提供了 NIO 的网络通信库——KryoNet,你若感兴趣的话可以自行查询和了解一下。
Hessian2
支持动态类型、跨语言的序列化协议,Java 对象序列化的二进制流可以被其他语言使用。Hessian2 序列化之后的数据可以进行自描述,不会像 Avro 那样依赖外部的 Schema 描述文件或者接口定义。Hessian2 可以用一个字节表示常用的基础类型,这极大缩短了序列化之后的二进制流。需要注意的是,在 Dubbo 中使用的 Hessian2 序列化并不是原生的 Hessian2 序列化,而是阿里修改过的 Hessian Lite,它是 Dubbo 默认使用的序列化方式。其序列化之后的二进制流大小大约是 Java 序列化的 50%,序列化耗时大约是 Java 序列化的 30%,反序列化耗时大约是 Java 序列化的 20%。
Protobuf(Google Protocol Buffers)
Google 公司开发的一套灵活、高效、自动化的、用于对结构化数据进行序列化的协议。但相比于常用的 JSON 格式,Protobuf 有更高的转化效率,时间效率和空间效率都是 JSON 的 5 倍左右。Protobuf 可用于通信协议、数据存储等领域,它本身是语言无关、平台无关、可扩展的序列化结构数据格式。目前 Protobuf提供了 C++、Java、Python、Go 等多种语言的 API,gRPC 底层就是使用 Protobuf 实现的序列化。