dubbo源碼解析(四十二)序列化——開篇

序列化——開篇

目標:介紹dubbo中序列化的內容,對dubbo中支持的序列化方式作對比,介紹dubbo-serialization-api下的源碼

前言

序列化就是將對象轉成字節流,用於網絡傳輸,以及將字節流轉爲對象,用於在收到字節流數據後還原成對象。序列化的好處我就很少說了,無非就是安全性更好、可跨平臺等。網上有不少總結的很好,我在這裏主要講講dubbo中序列化的設計和實現了哪些序列化方式。java

dubbo在2.6.x版本中,支持五種序列化方式,分別是git

  1. fastjson:依賴阿里的fastjson庫,功能強大(支持普通JDK類包括任意Java Bean Class、Collection、Map、Date或enum)
  2. fst:徹底兼容JDK序列化協議的系列化框架,序列化速度大概是JDK的4-10倍,大小是JDK大小的1/3左右。
  3. hessian2:hessian是一種跨語言的高效二進制序列化方式。但這裏實際不是原生的hessian2序列化,而是阿里修改過的hessian lite,它是dubbo RPC默認啓用的序列化方式
  4. jdk:JDK自帶的Java序列化實現。
  5. kryo:是一個快速序列化/反序列化工具,其使用了字節碼生成機制(底層依賴了 ASM 庫),所以具備比較好的運行速度,速度快,序列化後體積小,跨語言支持較複雜

在dubbo最新的2.7.0版本中支持了protostuff,以前的版本dubbo還實現了本身的dubbo序列化,可是因爲還不夠成熟,全部暫時移除了dubbo序列化的實現。github

從性能上對比,fst和kryo>hessian2>fastjson>jdk。json

他們具體的實現我不講解,由於不少都直接使用了對應的依賴褲,我只講解dubbo序列化的接口設計。api

serialization

源碼分析

(一)DataInput

public interface DataInput {

    /**
     * Read boolean.
     * 讀取布爾類型
     * @return boolean.
     * @throws IOException
     */
    boolean readBool() throws IOException;

    /**
     * Read byte.
     * 讀取字節
     * @return byte value.
     * @throws IOException
     */
    byte readByte() throws IOException;

    /**
     * Read short integer.
     * 讀取short類型
     * @return short.
     * @throws IOException
     */
    short readShort() throws IOException;

    /**
     * Read integer.
     * 讀取integer類型
     * @return integer.
     * @throws IOException
     */
    int readInt() throws IOException;

    /**
     * Read long.
     * 讀取long類型
     * @return long.
     * @throws IOException
     */
    long readLong() throws IOException;

    /**
     * Read float.
     * 讀取float類型
     * @return float.
     * @throws IOException
     */
    float readFloat() throws IOException;

    /**
     * Read double.
     * 讀取double類型
     * @return double.
     * @throws IOException
     */
    double readDouble() throws IOException;

    /**
     * Read UTF-8 string.
     * 讀取UTF-8 string
     * @return string.
     * @throws IOException
     */
    String readUTF() throws IOException;

    /**
     * Read byte array.
     * 讀取byte數組
     * @return byte array.
     * @throws IOException
     */
    byte[] readBytes() throws IOException;
}

該接口是數據輸入接口,能夠看到定義了從 InputStream 中各種數據類型的讀取方法。數組

(二)DataOutput

public interface DataOutput {

    /**
     * Write boolean.
     * 輸出boolean類型
     * @param v value.
     * @throws IOException
     */
    void writeBool(boolean v) throws IOException;

    /**
     * Write byte.
     * 輸出byte類型
     * @param v value.
     * @throws IOException
     */
    void writeByte(byte v) throws IOException;

    /**
     * Write short.
     * 輸出short類型
     * @param v value.
     * @throws IOException
     */
    void writeShort(short v) throws IOException;

    /**
     * Write integer.
     * 輸出integer類型
     * @param v value.
     * @throws IOException
     */
    void writeInt(int v) throws IOException;

    /**
     * Write long.
     * 輸出long類型
     * @param v value.
     * @throws IOException
     */
    void writeLong(long v) throws IOException;

    /**
     * Write float.
     * 輸出float類型
     * @param v value.
     * @throws IOException
     */
    void writeFloat(float v) throws IOException;

    /**
     * Write double.
     * 輸出double類型
     * @param v value.
     * @throws IOException
     */
    void writeDouble(double v) throws IOException;

    /**
     * Write string.
     * 輸出string類型
     * @param v value.
     * @throws IOException
     */
    void writeUTF(String v) throws IOException;

    /**
     * Write byte array.
     * 輸出byte數組
     * @param v value.
     * @throws IOException
     */
    void writeBytes(byte[] v) throws IOException;

    /**
     * Write byte array.
     * 輸出byte數組中部分數據
     * @param v   value.
     * @param off offset.
     * @param len length.
     * @throws IOException
     */
    void writeBytes(byte[] v, int off, int len) throws IOException;

    /**
     * Flush buffer.
     * 刷新緩衝區
     * @throws IOException
     */
    void flushBuffer() throws IOException;
}

該接口是數據輸出接口,能夠看到定義了向 InputStream 中,寫入基本類型的數據。安全

(三)ObjectOutput

public interface ObjectOutput extends DataOutput {

    /**
     * write object.
     * 輸入object類型
     * @param obj object.
     */
    void writeObject(Object obj) throws IOException;

}

在 DataOutput 的基礎上,增長寫入object類型的數據。網絡

(四)ObjectInput

public interface ObjectInput extends DataInput {

    /**
     * read object.
     * 讀取object類型數據
     * @return object.
     */
    Object readObject() throws IOException, ClassNotFoundException;

    /**
     * read object.
     * 根據class類型讀取object類型數據
     * @param cls object type.
     * @return object.
     */
    <T> T readObject(Class<T> cls) throws IOException, ClassNotFoundException;

    /**
     * read object.
     * 取object類型數據
     * @param cls object type.
     * @return object.
     */
    <T> T readObject(Class<T> cls, Type type) throws IOException, ClassNotFoundException;

}

該接口是繼承了DataInput 接口,在 DataInput 的基礎上,增長讀取object類型的數據。框架

(五)Cleanable

public interface Cleanable {

    /**
     * 清理
     */
    void cleanup();
}

該接口是清理接口,定義了一個清理方法。目前只有kryo實現的時候,完成序列化或反序列化,須要作清理。經過實現該接口,執行清理的邏輯。工具

(六)Serialization

@SPI("hessian2")
public interface Serialization {

    /**
     * get content type id
     * 得到內容類型編號
     * @return content type id
     */
    byte getContentTypeId();

    /**
     * get content type
     * 得到內容類型名
     * @return content type
     */
    String getContentType();

    /**
     * create serializer
     * 建立 ObjectOutput 對象,序列化輸出到 OutputStream
     * @param url
     * @param output
     * @return serializer
     * @throws IOException
     */
    @Adaptive
    ObjectOutput serialize(URL url, OutputStream output) throws IOException;

    /**
     * create deserializer
     * 建立 ObjectInput 對象,從 InputStream 反序列化
     * @param url
     * @param input
     * @return deserializer
     * @throws IOException
     */
    @Adaptive
    ObjectInput deserialize(URL url, InputStream input) throws IOException;

}

該接口是序列化接口,該接口也是可擴展接口,默認是使用hessian2序列化方式。其中定義了序列化和反序列化等方法

(七)SerializableClassRegistry

public abstract class SerializableClassRegistry {

    /**
     * 可序列化類類的集合
     */
    private static final Set<Class> registrations = new LinkedHashSet<Class>();

    /**
     * only supposed to be called at startup time
     * 把可序列化的類加入到集合
     */
    public static void registerClass(Class clazz) {
        registrations.add(clazz);
    }

    /**
     * 得到可序列化的類的集合
     * @return
     */
    public static Set<Class> getRegisteredClasses() {
        return registrations;
    }
}

該類提供一個序列化統一的註冊中心,其實就是封裝了可序列化類的集合

(八)SerializationOptimizer

public interface SerializationOptimizer {

    /**
     * 須要序列化的類的集合
     * @return
     */
    Collection<Class> getSerializableClasses();
}

該接口序列化優化器接口,在 Kryo 、FST 中,支持配置須要優化的類。業務系統中,能夠實現自定義的 SerializationOptimizer,進行配置。或者使用文件來配置也是一個選擇。

後記

該部分相關的源碼解析地址: https://github.com/CrazyHZM/i...

該文章講解了dubbo支持的幾種序列化方式,介紹了序列化的接口設計,具體的實現我再也不講述,由於大部分都是調用了不一樣的依賴庫。接下來我會說一個分割線,我講開始講解2.7.x版本的新特性,而後分析新特性的實現,下一篇就先講解一下dubbo2.7.0的大改動。

相關文章
相關標籤/搜索