從零開始實現簡單 RPC 框架 5:網絡通信之序列化

我們在接下來會開始講網絡通信相關的內容了。既然是網絡通信,那必然會涉及到序列化的相關技術。

下面是 ccx-rpc 序列化器的接口定義。

/**
 * 序列化器
 */
public interface Serializer {

    /**
     * 序列化
     *
     * @param object 要序列化的對象
     * @return 位元組數組
     */
    byte[] serialize(Object object);

    /**
     * 反序列化
     *
     * @param bytes 位元組數組
     * @param clazz 要反序列化的類
     * @param <T>   類型
     * @return 反序列化的對象
     */
    <T> T deserialize(byte[] bytes, Class<T> clazz);
}

接口只包含序列化、反序列化兩個最基礎的方法。不同的序列化器只需要實現這個接口即可,再配合 SPI 就可以使用了。
下面是 ccx-rpc 的一小段反序列化代碼:

// 獲取序列化類型
SerializeType serializeType = SerializeType.fromValue(codec);
// 獲取序列化器
Serializer serializer = ExtensionLoader.getLoader(Serializer.class).getExtension(serializeType.getName());
// 根據消息類型選擇反序列化的 Class
Class<?> clazz = messageType == MessageType.REQUEST.getValue() ? RpcRequest.class : RpcResponse.class;
// 進行反序列化
Object object = serializer.deserialize(decompressedBytes, clazz);

序列化算法有多種多樣,各有千秋,我們需要結合自己的業務,選擇合適的序列化算法。

序列化算法的選擇通常有下列一些常用的指標:

  • 通用性:是否跨語言,跨平台。如果 RPC 調用涉及到其他語言、平台,這個指標不可忽視。
  • 性能:通常指解析速度、序列化後的大小。序列化後的數據一般用於存儲或網絡傳輸,其大小是一個很重要的指標;解析的速度無需多言,當然是越快越好。
  • 可擴展性:系統升級不可避免,某一實體的屬性變更,會不會導致反序列化異常,也應該納入序列化算法的考量範圍。
  • 易用性:API 使用是否複雜,會影響開發效率。

下面我們來看一下常見的序列化算法。

常見序列化算法

1. Java 序列化

Java 序列化大家都很熟悉了,使用起來也不算複雜。先實現 Serializable,生成序列號 serialVersionUID,最後調用java.io.ObjectOutputStreamwriteObject() / readObject() 進行序列化與反序列化。

說實話,Java 序列化雖然知道,但是還沒真正去用過,這個使用步驟還是臨時搜的。。。

Java 序列化有個致命缺點:那就是不跨語言,而且性能也不太行。所以 Java 序列化很少人用,也成為了我們最熟悉的陌生人

2. FastJson

FastJson 是阿里開源的 JSON 解析庫。正如其名,「快」是其主要賣點。從官方的測試結果來看,FastJson 確實是最快的,比 Jackson 快 20% 左右,但是近幾年 FastJson 的安全漏洞比較多,而且版本升級可能會存在較大的兼容問題,所以在選擇的時候,還是需要謹慎一些。
JSON 的優點就是可讀性高,但是其序列化結果的體積比較大。

3. Jackson

Jackson 相對 FastJson 的功能比較多,安全漏洞也比較少,社區活躍。雖然性能相對於 Jackson 稍差,但是用着安心。
但是其序列化結果的體積比較大,對 RPC 框架來說,還是不大適合的。

4. Kryo

Kryo 是一個高效的 Java 序列化/反序列化庫,其特點是 API 代碼簡單,序列化速度快,並且序列化之後得到的數據比較小。
優點:接口易用、解析快、體積小
缺點:只支持 Java、增刪字段會異常

5. Hessian

Hessian 是一種支持動態類型、跨語言的序列化協議,Java 對象序列化的二進制流可以被其他語言使用。
優點:接口易用、解析快、支持多語言
缺點:異常機制不完善,提示信息不足

6. Protobuf

Google 公司開發的一套靈活、高效、自動化的、用於對結構化數據進行序列化的協議。相比於常用的 JSON 格式,Protobuf 有更高的轉化效率,時間效率和空間效率都是 JSON 的 5 倍左右。Protobuf 可用於通信協議、數據存儲等領域,它本身是語言無關、平台無關、可擴展的序列化結構數據格式。目前 Protobuf 提供了 C++JavaPythonGo 等多種語言的 API。
優點:解析快、體積小、支持多語言。
缺點:需要先定義 proto 結構,使用相對麻煩,不過 Java 可以使用 Protostuff 解決這個問題。

總結

在上文,我們介紹了序列化器的定義,很簡單,只有序列化,反序列化兩個方法。
然後,介紹了常見的序列化算法,例如Java 序列化、FastJson、Jackson、Kryo、Hessian、Protobuf 等。這些算法各有優缺點,大家在使用時,可以結合自己的業務情況進行選擇。

ccx-rpc 代碼已經開源
Github://github.com/chenchuxin/ccx-rpc
Gitee://gitee.com/imccx/ccx-rpc