【剖析 | SOFARPC 框架】系列之 SOFARPC 序列化比較

前言

在應用服務化架構中,RPC 框架是很是重要的基礎組件。而在 RPC 框架當中,序列化(以及反序列化)又是必不可少的一環。由於序列化的性能對總體框架性能有比較大的影響,以前的文章中,咱們已經詳細剖析了 SOFARPC 各個核心功能模塊的實現原理,想必你們已經很清楚 RPC 的調用流程。
在整個 RPC 調用流程當中,序列化及反序列化起到了承上啓下的做用。序列化時,RPC客戶端把待調用的方法和參數對象轉換爲網絡上可傳輸的字節序列,爲進一步的編解碼提供原料。反序列化時,把從網絡上接收到且已經解碼了的字節序列轉換成對象,便於 RPC 服務端調用。
本文將從序列化概述、序列化協議特性、序列化使用方法分類、SOFARPC 序列化的設計及實現、幾種序列化協議對比等方面介紹及對比序列化及其在 SOFARPC 中的應用。


序列化概述

RPC 調用經過網絡傳輸相關的調用方法及參數,在這個網絡傳輸過程當中,內存中的對象是沒法直接傳輸的,只有二進制字節才能在網絡上傳輸。而爲了實現調用對象在網絡上的傳輸,必須經過序列化實現對象 -> 字節的過程,以及反序列化實現字節 -> 對象的過程。在網絡協議模型中,序列化屬於應用層協議的一部分。
以下列定義:
序列化:將數據結構或者對象轉換成二進制串的過程。
反序列化:將序列化過程當中生成的二進制串轉換成數據結構或者對象的過程。
在上述定義中,二進制字節數組專指 Java 語言中的 byte[]

序列化協議特性

每種序列化協議都有其優勢和缺點,在對一個序列化協議進行衡量評判時,一般由以下一些指標能夠參考:
指標
說明
重要性
通用性
是否跨平臺,社區如何
中高
可讀
序列化格式是否可讀
中低
易用性
是否簡單易用
中高
性能
序列化後的大小和壓縮 CPU消耗
中高
可擴展性
是在容許字段修改
安全性
是否存在一些沒法修復的漏洞
如下逐個來詳細說明:

通用性

在通用性上,主要考察該序列化協議是否支持跨平臺、跨語言的使用,同時兼顧考察業界的流行度及社區的活躍性。

可讀/易用性

在可讀、易用性上面,主要考察該序列化協議序列化以後是否人眼可讀,如 XML 和 JSON 就是人眼可讀的序列化框架,這會大大提升調試的效率。同時,須要考察序列化框架所提供的 API 是否容易學習、調用。固然,在遠程調用 的場景下,可讀性不是一個重要因素。或者說,咱們更多但願不可讀。來保證必定的安全性。

性能

性能指標,主要考慮序列化框架的時間複雜度和空間複雜度。
序列化以後的數據通常都是用於存儲或者網絡傳輸,空間佔用大小決定了傳輸的效率。序列化一般狀況下要在原有的數據上加上描述字段,若是這個過程當中引入的額外開銷過大,則在大規模分佈式系統中,極可能會形成巨大的額外空間開銷。
同時,爲了提升系統的性能,是否耗費 CPU,解析和反解析二進制串的時間也是一個很是重要的指標。

可擴展性

主要考慮當系統準備升級,須要對實體的屬性進行變動,此時序列化協議可否快速支持,而且不會對原有的系統形成影響。如做爲服務提供方的 API 接口入參中,增長了一個字段,是否必定要強制全部的客戶端進行升級。這個會涉及到線上兼容性的問題。通常咱們要求新增字段,在客戶端還沒有使用的狀況下,不該該有序列化問題。

安全性

須要考察序列化協議是否支持跨局域網之間的安全訪問。是否存在一些安全漏洞。能夠經過構造一些字節數組,使得服務端反序列化的時候,觸發某些安全漏洞,執行一些系統調用,或者越權操做。

序列化使用方式分類

按照序列化的使用方式,能夠分爲自描述型序列化以及基於中間格式型序列化。

自描述型

所謂的自描述型,即在序列化的字節流裏有着完整的對象類型信息和屬性信息,能夠在不依賴任何外界描述信息的前提下,只要拿到這個二進制流,就能夠直接還原出原始對象。
相似的系列化產品有: hessianJSONXML 等。
例如,有以下一個對象 Person,Java 語言定義以下:
package com.sofa.test.Person;

public class Person {
    private int age = 15;
    private String name = 「sofa」;
}
複製代碼
則使用 hessian 序列化後的字節流以下:
M**com.sofa.test.PersonS**nameS**sofaS**ageI**b3 b2 b1 b0 z
上面的*和b3 b2 b1 b0都表示不可打印的二進制。從上面內容能夠看出,按照相應規定就能從二進制串中反序列化出對象來。由於這裏面已經描述了類型,類型的字段名,以及對應的值,這樣就能夠直接反序列化了。

基於中間描述型

通常這種類型的序列化主要用於跨語言當中,好比 Protobuf以及 thrift 等等。在使用時都須要事先定義一箇中間格式的文件(IDL 文件),而後根據不一樣語言的生成工具生成一個相應語言的可序列化類。如下是一個簡單的 Proto的描述文件
message SofaApp{
    string appName = 1;
    repeated string authList = 2;
    repeated string serviceList = 3;
}
複製代碼
而後當須要反序列化時,根據 IDL 文件及逆行相應的反序列化便可。格式是這樣
其中,圖中的用戶定義編號就是前面 proto中對每一個字段定義的編號。

SOFARPC 序列化的設計與實現

SOFARPC 支持及將要支持的序列化協議有: hessianProtobufJson

序列化接口定義

在目前的 SOFARPC 5.4 分支中,已經支持的序列化協議有 hessianProtobuf。兩個序列化實現類繼承了 AbstractSerializer 抽象類,該抽象類又實現了以下的 Serializer 接口:
/**
 * 序列化器接口
 *
 * @author <a href=mailto:zhanggeng.zg@antfin.com>GengZhang</a>
 */
@Extensible(coded = true)
@Unstable
public interface Serializer {

    /**
     * 序列化
     *
     * @param object  對象
     * @param context 上下文
     * @return 序列化後的對象
     * @throws SofaRpcException 序列化異常
     */
    public AbstractByteBuf encode(Object object, Map<String, String> context) throws SofaRpcException;

    /**
     * 反序列化,只有類型,返回對象
     *
     * @param data    原始字節數組
     * @param clazz   指望的類型
     * @param context 上下文
     * @return 反序列化後的對象
     * @throws SofaRpcException 序列化異常
     */
    public Object decode(AbstractByteBuf data, Class clazz, Map<String, String> context) throws SofaRpcException;

    /**
     * 反序列化,已有數據,填充字段
     *
     * @param data     原始字節數組
     * @param template 模板對象
     * @param context  上下文
     * @throws SofaRpcException 序列化異常
     */
    public void decode(AbstractByteBuf data, Object template, Map<String, String> context) throws SofaRpcException;
}
複製代碼
從上面的接口定義能夠看出,序列化方法傳入待序列化對象及相應的上下文參數,最後生成序列化的對象。
反序列化則是重載的兩個方法,在傳入字節數據及上下文的時候,分別還能夠傳入指望的類型或者模板。
序列化協議對象的獲取則經過 SerializerFactory 序列化工廠傳入序列化名稱獲取,獲取到的序列化協議對象再對傳入的數據進行相應的序列化與反系列化操做。
目前 SOFARPC 序列化支持協議,SOFA-Hessian,Protobuf,泛化調用序列化(hessian),Jackson。

幾種序列化協議對比

序列化協議
簡要介紹
優勢
缺點
SOFA-Hessian
hessian2協議,安全改進
Java友好,性能較高
跨語言支持通常
Kryo
Kryo框架
速度快,序列化後體積小
跨語言支持較複雜 ,有一個限制,就是若是服務端增刪字段,客戶端沒有更新會失敗,不支持無參構造函數
Protobuf
中間描述型
跨語言,性能高
使用不夠友好,生成類可讀性差,須要工具輔助。
JDK
JVM原生序列化支持
使用方便,無需引入額外依賴
速度慢,佔空間,有安全問題,已經再也不使用
JSON
各類 json庫直接使用
跨語言,使用簡單,格式可讀
序列化結果大小較大,性能通常,可能存在反序列化漏洞。
這裏咱們只介紹了幾種常見的,或者你們使用比較多的。對於一些其餘不常見的序列化框架的性能和優缺點,能夠參看參考文檔中的 wiki,很是見的序列化框架可能存在更多的潛在限制,若是選型,須要特別注意。

參考資料

SOFARPC 框架之整體設計與擴展機制: mp.weixin.qq.com/s/ZKUmmFT0N…
序列化和反序列化: www.infoq.com/cn/articles…
序列化性能比較: github.com/eishay/jvm-…
高效的數據壓縮編碼方式 Protobuf: halfrost.com/protobuf_en…

結語

本文主要對 SOFARPC 序列化的內容進行了總括性的介紹。講述了序列化的定義及序列化框架的基本特性,同時對 SOFARPC 框架序列化的流程進行了說明。 在設計和選擇 RPC 框架序列化協議的時候,能夠根據實際狀況進行選擇。

長按關注,獲取分佈式架構乾貨git

歡迎你們共同打造 SOFAStack https://github.com/alipaygithub

相關文章
相關標籤/搜索