天天看點

Dubbo的多種序列化算法(上)1 JDK序列化操作2 常見序列化算法

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 實作的序列化。