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

小新是也發表於2021-08-27

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

下面是 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:https://github.com/chenchuxin/ccx-rpc
Gitee:https://gitee.com/imccx/ccx-rpc

相關文章