<bdo id="ks4iu"><del id="ks4iu"></del></bdo>
  • 
    <pre id="ks4iu"></pre>
  • <bdo id="ks4iu"><del id="ks4iu"></del></bdo>
    <input id="ks4iu"><em id="ks4iu"></em></input>
    
    
  • <center id="ks4iu"><cite id="ks4iu"></cite></center>
  • 首頁 > 空調(diào) >

    招銀網(wǎng)絡(luò)二面:什么是序列化?常見的序列化協(xié)議有哪些?

    你好,我是 Guide。今天分享一道讀者面試招銀網(wǎng)絡(luò)科技遇到的面試真題。

    下面是正文。

    序列化和反序列化相關(guān)概念

    什么是序列化?什么是反序列化?

    如果我們需要持久化 Java 對(duì)象比如將 Java 對(duì)象保存在文件中,或者在網(wǎng)絡(luò)上傳輸 Java 對(duì)象,這些場(chǎng)景都需要用到序列化。

    簡單來說:

    序列化

    :將數(shù)據(jù)結(jié)構(gòu)或?qū)ο筠D(zhuǎn)換成二進(jìn)制字節(jié)流的過程

    反序列化

    :將在序列化過程中所生成的二進(jìn)制字節(jié)流的過程轉(zhuǎn)換成數(shù)據(jù)結(jié)構(gòu)或者對(duì)象的過程

    對(duì)于 Java 這種面向?qū)ο缶幊陶Z言來說,我們序列化的都是對(duì)象(Object)也就是實(shí)例化后的類(Class),但是在 C++這種半面向?qū)ο蟮恼Z言中,struct(結(jié)構(gòu)體)定義的是數(shù)據(jù)結(jié)構(gòu)類型,而 class 對(duì)應(yīng)的是對(duì)象類型。

    維基百科是如是介紹序列化的:

    序列化

    (serialization)在計(jì)算機(jī)科學(xué)的數(shù)據(jù)處理中,是指將數(shù)據(jù)結(jié)構(gòu)或?qū)ο鬆顟B(tài)轉(zhuǎn)換成可取用格式(例如存成文件,存于緩沖,或經(jīng)由網(wǎng)絡(luò)中發(fā)送),以留待后續(xù)在相同或另一臺(tái)計(jì)算機(jī)環(huán)境中,能恢復(fù)原先狀態(tài)的過程。依照序列化格式重新獲取字節(jié)的結(jié)果時(shí),可以利用它來產(chǎn)生與原始對(duì)象相同語義的副本。對(duì)于許多對(duì)象,像是使用大量引用的復(fù)雜對(duì)象,這種序列化重建的過程并不容易。面向?qū)ο笾械膶?duì)象序列化,并不概括之前原始對(duì)象所關(guān)系的函數(shù)。這種過程也稱為對(duì)象編組(marshalling)。從一系列字節(jié)提取數(shù)據(jù)結(jié)構(gòu)的反向操作,是反序列化(也稱為解編組、deserialization、unmarshalling)。

    綜上:

    序列化的主要目的是通過網(wǎng)絡(luò)傳輸對(duì)象或者說是將對(duì)象存儲(chǔ)到文件系統(tǒng)、數(shù)據(jù)庫、內(nèi)存中。

    實(shí)際開發(fā)中有哪些用到序列化和反序列化的場(chǎng)景?

    對(duì)象在進(jìn)行網(wǎng)絡(luò)傳輸(比如遠(yuǎn)程方法調(diào)用 RPC 的時(shí)候)之前需要先被序列化,接收到序列化的對(duì)象之后需要再進(jìn)行反序列化;

    將對(duì)象存儲(chǔ)到文件中的時(shí)候需要進(jìn)行序列化,將對(duì)象從文件中讀取出來需要進(jìn)行序列化。

    將對(duì)象存儲(chǔ)到緩存數(shù)據(jù)庫(如 Redis)時(shí)需要用到序列化,將對(duì)象從緩存數(shù)據(jù)庫中讀取出來需要反序列化。

    序列化協(xié)議對(duì)應(yīng)于 TCP/IP 4 層模型的哪一層?

    我們知道網(wǎng)絡(luò)通信的雙方必須要采用和遵守相同的協(xié)議。TCP/IP 四層模型是下面這樣的,序列化協(xié)議屬于哪一層呢?

    應(yīng)用層

    傳輸層

    網(wǎng)絡(luò)層

    網(wǎng)絡(luò)接口層

    TCP/IP 4層模型

    如上圖所示,OSI 七層協(xié)議模型中,表示層做的事情主要就是對(duì)應(yīng)用層的用戶數(shù)據(jù)進(jìn)行處理轉(zhuǎn)換為二進(jìn)制流。反過來的話,就是將二進(jìn)制流量轉(zhuǎn)換成應(yīng)用層的用戶數(shù)據(jù)。這不就對(duì)應(yīng)的是序列化和反序列化么?

    因?yàn)椋琌SI 七層協(xié)議模型中的應(yīng)用層、表示層和會(huì)話層對(duì)應(yīng)的都是 TCP/IP 四層模型中的應(yīng)用層,所以序列化協(xié)議屬于 TCP/IP 協(xié)議應(yīng)用層的一部分。

    常見序列化協(xié)議對(duì)比

    JDK 自帶的序列化方式一般不會(huì)用 ,因?yàn)樾蛄谢实筒⑶也糠职姹居邪踩┒?。比較常用的序列化協(xié)議有 hessian、kyro、protostuff。

    下面提到的都是基于二進(jìn)制的序列化協(xié)議,像 JSON 和 XML 這種屬于文本類序列化方式。雖然 JSON 和 XML 可讀性比較好,但是性能較差,一般不會(huì)選擇。

    JDK 自帶的序列化方式

    JDK 自帶的序列化,只需實(shí)現(xiàn)

    java.io.Serializable

    接口即可。

    @AllArgsConstructor

    @NoArgsConstructor

    @Getter

    @Builder

    @ToString

    public class RpcRequest implements Serializable {

    private static final long serialVersionUID = 1905122041950251207L;

    private String requestId;

    private String interfaceName;

    private String methodName;

    private Object[] parameters;

    private Class[] paramTypes;

    private RpcMessageTypeEnum rpcMessageTypeEnum;

    }

    序列化號(hào) serialVersionUID 屬于版本控制的作用。序列化的時(shí)候 serialVersionUID 也會(huì)被寫入二級(jí)制序列,當(dāng)反序列化時(shí)會(huì)檢查 serialVersionUID 是否和當(dāng)前類的 serialVersionUID 一致。如果 serialVersionUID 不一致則會(huì)拋出

    InvalidClassException

    異常。強(qiáng)烈推薦每個(gè)序列化類都手動(dòng)指定其

    serialVersionUID

    ,如果不手動(dòng)指定,那么編譯器會(huì)動(dòng)態(tài)生成默認(rèn)的序列化號(hào)

    我們很少或者說幾乎不會(huì)直接使用這個(gè)序列化方式,主要原因有兩個(gè):

    不支持跨語言調(diào)用

    : 如果調(diào)用的是其他語言開發(fā)的服務(wù)的時(shí)候就不支持了。

    性能差

    :相比于其他序列化框架性能更低,主要原因是序列化之后的字節(jié)數(shù)組體積較大,導(dǎo)致傳輸成本加大。

    Kryo

    Kryo 是一個(gè)高性能的序列化/反序列化工具,由于其變長存儲(chǔ)特性并使用了字節(jié)碼生成機(jī)制,擁有較高的運(yùn)行速度和較小的字節(jié)碼體積。

    另外,Kryo 已經(jīng)是一種非常成熟的序列化實(shí)現(xiàn)了,已經(jīng)在 Twitter、Groupon、Yahoo 以及多個(gè)著名開源項(xiàng)目(如 Hive、Storm)中廣泛的使用。

    guide-rpc-framework[1]

    就是使用的 kyro 進(jìn)行序列化,序列化和反序列化相關(guān)的代碼如下:

    /**

    * Kryo serialization class, Kryo serialization efficiency is very high, but only compatible with Java language

    *

    * @author shuang.kou

    * @createTime 2020年05月13日 19:29:00

    */

    @Slf4j

    public class KryoSerializer implements Serializer {

    /**

    * Because Kryo is not thread safe. So, use ThreadLocal to store Kryo objects

    */

    private final ThreadLocal kryoThreadLocal = ThreadLocal.withInitial(() -> {

    Kryo kryo = new Kryo();

    kryo.register(RpcResponse.class);

    kryo.register(RpcRequest.class);

    return kryo;

    });

    @Override

    public byte[] serialize(Object obj) {

    try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

    Output output = new Output(byteArrayOutputStream)) {

    Kryo kryo = kryoThreadLocal.get();

    // Object->byte:將對(duì)象序列化為byte數(shù)組

    kryo.writeObject(output, obj);

    kryoThreadLocal.remove();

    return output.toBytes();

    } catch (Exception e) {

    throw new SerializeException("Serialization failed");

    }

    }

    @Override

    public T deserialize(byte[] bytes, Class clazz) {

    try (ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);

    Input input = new Input(byteArrayInputStream)) {

    Kryo kryo = kryoThreadLocal.get();

    // byte->Object:從byte數(shù)組中反序列化出對(duì)對(duì)象

    Object o = kryo.readObject(input, clazz);

    kryoThreadLocal.remove();

    return clazz.cast(o);

    } catch (Exception e) {

    throw new SerializeException("Deserialization failed");

    }

    }

    }

    Github 地址:

    Protobuf

    Protobuf 出自于 Google,性能還比較優(yōu)秀,也支持多種語言,同時(shí)還是跨平臺(tái)的。就是在使用中過于繁瑣,因?yàn)槟阈枰约憾x IDL 文件和生成對(duì)應(yīng)的序列化代碼。這樣雖然不然靈活,但是,另一方面導(dǎo)致 protobuf 沒有序列化漏洞的風(fēng)險(xiǎn)。

    Protobuf 包含序列化格式的定義、各種語言的庫以及一個(gè) IDL 編譯器。正常情況下你需要定義 proto 文件,然后使用 IDL 編譯器編譯成你需要的語言

    一個(gè)簡單的 proto 文件如下:

    // protobuf的版本

    syntax = "proto3";

    // SearchRequest會(huì)被編譯成不同的編程語言的相應(yīng)對(duì)象,比如Java中的class、Go中的struct

    message Person {

    //string類型字段

    string name = 1;

    // int 類型字段

    int32 age = 2;

    }

    Github 地址:

    。

    ProtoStuff

    由于 Protobuf 的易用性,它的哥哥 Protostuff 誕生了。

    protostuff 基于 Google protobuf,但是提供了更多的功能和更簡易的用法。雖然更加易用,但是不代表 ProtoStuff 性能更差。

    Github 地址:

    。

    hession

    hessian 是一個(gè)輕量級(jí)的,自定義描述的二進(jìn)制 RPC 協(xié)議。hessian 是一個(gè)比較老的序列化實(shí)現(xiàn)了,并且同樣也是跨語言的。

    dubbo RPC 默認(rèn)啟用的序列化方式是 hession2 ,但是,Dubbo 對(duì) hessian2 進(jìn)行了修改,不過大體結(jié)構(gòu)還是差不多。

    總結(jié)

    Kryo 是專門針對(duì) Java 語言序列化方式并且性能非常好,如果你的應(yīng)用是專門針對(duì) Java 語言的話可以考慮使用,并且 Dubbo 官網(wǎng)的一篇文章中提到說推薦使用 Kryo 作為生產(chǎn)環(huán)境的序列化方式。(文章地址:

    )

    像 Protobuf、 ProtoStuff、hession 這類都是跨語言的序列化方式,如果有跨語言需求的話可以考慮使用。

    除了我上面介紹到的序列化方式的話,還有像 Thrift,Avro 這些。

    其他推薦閱讀

    美團(tuán)技術(shù)團(tuán)隊(duì)-序列化和反序列化:

    在 Dubbo 中使用高效的 Java 序列化(Kryo 和 FST):

    參考資料

    [1]

    guide-rpc-framework:

    [2]

    [3]

    [4]

    [5]

    [6]

    [7]

    ·········· END ··············

    責(zé)任編輯:Rex_08

    關(guān)鍵詞: @ToString Java
    推薦閱讀
    欧美国产在线一区,免费看成年视频网页,国产亚洲福利精品一区,亚洲一区二区约美女探花
    <bdo id="ks4iu"><del id="ks4iu"></del></bdo>
  • 
    <pre id="ks4iu"></pre>
  • <bdo id="ks4iu"><del id="ks4iu"></del></bdo>
    <input id="ks4iu"><em id="ks4iu"></em></input>
    
    
  • <center id="ks4iu"><cite id="ks4iu"></cite></center>
  • 主站蜘蛛池模板: 毛片网在线观看| 骚虎视频在线免费观看| 欧美毛多水多肥妇| 日韩人妻精品一区二区三区视频| 在线视频免费国产成人| 国产亚洲成AV人片在线观看| 亚洲人xxx日本人18| 6080午夜一级毛片免费看| 精品国产一区二区三区久久| 日本在线视频www色| 国产欧美日产中文| 亚洲欧美一区二区三区电影| √天堂中文官网在线| 美女视频黄频a免费| 日本不卡视频免费| 国产成年女人特黄特色毛片免| 亚洲AV无码一区二区二三区软件| 69日本xxxxxxxxx19| 欧美乱妇高清无乱码免费| 在线观看网址入口2020国产| 亚洲视频免费播放| z0z0z0另类极品| 激情伊人五月天久久综合| 小小的日本三电影免费观看| 啊轻点灬大ji巴太粗太长了情侣 | 无主之花2025韩语中字| 国产在线拍偷自揄拍无码| 亚洲一区无码中文字幕| 黄色一级黄色片| 日韩精品一区二区三区视频| 国产男女猛视频在线观看| 亚洲国产精品成人午夜在线观看| 91精品在线看| 欧美综合区自拍亚洲综合天堂| 夜夜精品无码一区二区三区| 亚洲日韩精品无码专区网址| 337p欧美日本超大胆艺术裸| 欧美精品久久一区二区三区| 国产欧美日韩另类va在线| 久久99蜜桃精品久久久久小说| 茄子视频国产在线观看|