結(jié)構(gòu)化數(shù)據(jù)傳輸協(xié)議:json與protobuf

跨平臺(tái)的結(jié)構(gòu)化數(shù)據(jù)傳輸協(xié)議一般情況下關(guān)注三要素和三件事:

  • 三要素
  1. protocal
  2. 數(shù)據(jù)
  3. API
  • 三件事
  1. 協(xié)議編譯
  2. 序列化
  3. 反序列化

以下三種協(xié)議按照以上要素進(jìn)行介紹

json(javascript object notation)

  • 三要素
  1. protocal:面向javascript,使用eval()自動(dòng)轉(zhuǎn)換成遠(yuǎn)程的對(duì)象,面向其他語(yǔ)言需要自己編寫model并解析
  2. 數(shù)據(jù):包含多種數(shù)據(jù)類型,對(duì)象(字典表示法),數(shù)組(同質(zhì)化元素集合),string(基本類型,可以用來(lái)作為鍵或者值),nil(空)等
  3. API:引入json的包,可以提供建立json對(duì)象,讀入(從網(wǎng)絡(luò)或者本地)json數(shù)據(jù),寫出(網(wǎng)絡(luò)或者本地)json數(shù)據(jù)的接口,并且提供顯式類型轉(zhuǎn)換的接口
  • 三件事
  1. 協(xié)議編譯:不經(jīng)過(guò)特殊編譯,除非針對(duì)特定語(yǔ)言產(chǎn)生了特定的轉(zhuǎn)換接口,傳輸?shù)氖俏谋緮?shù)據(jù),所以是自描述型的,發(fā)送方和接收方事先約定好傳輸數(shù)據(jù)的格式
    2 序列化:發(fā)送方將對(duì)象數(shù)據(jù)手動(dòng)寫入json對(duì)象中,由json庫(kù)自動(dòng)完成序列化工作
    3 反序列化:接受方讀出json數(shù)據(jù),然后使用json接口獲取相應(yīng)數(shù)據(jù)寫入對(duì)象
  • 特性
  1. 因?yàn)閾碛凶悦枋鲂裕⑶乙晕谋痉绞絺鬏敂?shù)據(jù),所以可擴(kuò)展,可編輯
  2. 擁有良好的跨平臺(tái)和跨語(yǔ)言特性(提供不同的庫(kù))
  3. 使用范圍較廣,支持的應(yīng)用場(chǎng)景較為豐富,靈活的語(yǔ)法可以傳輸更廣泛的數(shù)據(jù)
  4. 文本傳輸,沒(méi)有經(jīng)過(guò)壓縮,并且?guī)в幸欢ǖ母袷綌U(kuò)展,效率比XML優(yōu),比protobuf差

注意:不同的json庫(kù)對(duì)數(shù)據(jù)的處理方式不一樣,cjson采用深度拷貝的方式,所以記得銷毀數(shù)據(jù),而在某些優(yōu)化場(chǎng)景下是采用淺層拷貝的方式,此時(shí)記得考慮數(shù)據(jù)變動(dòng)的協(xié)同性。

protobuf的概念

  • 三要素:
  1. 協(xié)議:編寫proto文件,類似于java和c++的類定義,但是更具有通用性(提供各種面向語(yǔ)言的編譯庫(kù)),并且采用編號(hào)預(yù)處理
  2. 數(shù)據(jù):提供更加豐富的數(shù)據(jù)類型,基本可以和高級(jí)語(yǔ)言一一對(duì)應(yīng)
  3. API: 根據(jù)平臺(tái)提供各種數(shù)據(jù)處理的api,同時(shí)根據(jù)proto文件產(chǎn)生特定的api
  • 三件事
  1. 協(xié)議編譯:編寫proto文件,編譯器自動(dòng)編譯,產(chǎn)生特定語(yǔ)言的類型
  2. 序列化:一切建立在proto生成的類型之上,建立對(duì)象,采用數(shù)組形式或者api方式寫入數(shù)據(jù),由庫(kù)直接序列化成二進(jìn)制文件,所以相關(guān)數(shù)據(jù)不可編輯;
  3. 反序列化:讀入對(duì)象,直接使用(良好的類型匹配)

protobuf的特性

  • protocol buffers 是一種語(yǔ)言無(wú)關(guān)(協(xié)議的跨語(yǔ)言編譯)、平臺(tái)無(wú)關(guān)(跨平臺(tái)編譯)、可擴(kuò)展(可以在proto里面改變類型信息,同時(shí)采用動(dòng)態(tài)編譯的方式支持無(wú)痕擴(kuò)展)的序列化結(jié)構(gòu)數(shù)據(jù)的方法,它可用于(數(shù)據(jù))通信協(xié)議、數(shù)據(jù)存儲(chǔ)等。

  • Protocol Buffers 是一種靈活,高效,自動(dòng)化機(jī)制的結(jié)構(gòu)數(shù)據(jù)序列化方法-可類比 XML,但是比 XML 更?。? ~ 10倍)、更快(20 ~ 100倍)、更為簡(jiǎn)單。

  • 你可以定義數(shù)據(jù)的結(jié)構(gòu),然后使用特殊生成的源代碼輕松的在各種數(shù)據(jù)流中使用各種語(yǔ)言進(jìn)行編寫和讀取結(jié)構(gòu)數(shù)據(jù)。你甚至可以更新數(shù)據(jù)結(jié)構(gòu),而不破壞由舊數(shù)據(jù)結(jié)構(gòu)編譯的已部署程序。

protobuf的語(yǔ)法

  • 將字符串鍵值編成整形號(hào),提高傳輸效率,1-15占用一個(gè)字節(jié),大于15占用2個(gè)字節(jié)
  • proto文件格式:類似于python
    語(yǔ)法規(guī)則:syntax "proto3";
    在文件開頭定義一個(gè):package 文件名;
    引入其他文件:import 文件名;
    可選字段:option 參數(shù)=xxx
    使用枚舉定義常量:enum {
    XXX=xxx;
    }
    結(jié)構(gòu)體字段(定義一個(gè)類型,并給數(shù)據(jù)成員做編號(hào)):message name{

}
最后proto文件會(huì)被編譯成相應(yīng)語(yǔ)言的二進(jìn)制文件

  • pb文件編寫

數(shù)據(jù)類型的對(duì)應(yīng)

image.png

序列化和反序列化本身不關(guān)注數(shù)據(jù)的傳輸,但是網(wǎng)絡(luò)傳輸?shù)臅r(shí)候,只有拿到整個(gè)序列化后的數(shù)據(jù),才能解析出對(duì)象,所以需要設(shè)計(jì)協(xié)議包括:header(根據(jù)不同的對(duì)象封裝相應(yīng)的規(guī)則,proto),主體

image.png

image.png

protobuf的不足

  • 語(yǔ)義簡(jiǎn)單,不能提供復(fù)雜數(shù)據(jù)格式,比如XML能夠定義的標(biāo)準(zhǔn)形式,XML解析器更加復(fù)雜
  • 不能對(duì)基于文本的標(biāo)記文檔進(jìn)行建模,一般用于數(shù)據(jù)結(jié)構(gòu)的建模上面(而文本不適合描述數(shù)據(jù)結(jié)構(gòu))
  • 數(shù)據(jù)結(jié)構(gòu)二進(jìn)制化,沒(méi)法直接編輯

高級(jí)技術(shù)

動(dòng)態(tài)編譯
  • 在一些無(wú)法獲取已知proto語(yǔ)義的網(wǎng)絡(luò)中間件中,需要?jiǎng)討B(tài)的去編譯proto文件,這大大提高了protobuf做為結(jié)構(gòu)化數(shù)據(jù)網(wǎng)絡(luò)傳輸?shù)耐ㄓ眯?/li>
關(guān)于性能的一些細(xì)節(jié)
  • protobuf的數(shù)據(jù)編碼方式
    數(shù)據(jù)單元編碼協(xié)議:對(duì)于每一個(gè)字節(jié),它的第一位用來(lái)標(biāo)志下一個(gè)字節(jié)是不是屬于當(dāng)前數(shù)據(jù). 所以單字節(jié)可以用來(lái)表示128以下的數(shù)字,以此類推。
    符號(hào)碼(key-value):每一個(gè)符號(hào)碼被編碼成key-value這兩個(gè)數(shù)據(jù)單元
    key用來(lái)標(biāo)定value的范圍:key=(field_number<<3)|wire,其中field_number為proto中對(duì)每一個(gè)數(shù)據(jù)域的編號(hào),wire指以下六種類型


    image.png

    對(duì)于負(fù)數(shù)采用zigzag編碼:


    image.png

    封解包的速度:
    首先我們來(lái)了解一下 XML 的封解包過(guò)程。XML 需要從文件中讀取出字符串,再轉(zhuǎn)換為 XML 文檔對(duì)象結(jié)構(gòu)模型。之后,再?gòu)?XML 文檔對(duì)象結(jié)構(gòu)模型中讀取指定節(jié)點(diǎn)的字符串,最后再將這個(gè)字符串轉(zhuǎn)換成指定類型的變量。這個(gè)過(guò)程非常復(fù)雜,其中將 XML 文件轉(zhuǎn)換為文檔對(duì)象結(jié)構(gòu)模型的過(guò)程通常需要完成詞法文法分析等大量消耗 CPU 的復(fù)雜計(jì)算。
    反觀 Protobuf,它只需要簡(jiǎn)單地將一個(gè)二進(jìn)制序列,按照指定的格式讀取到 C++ 對(duì)應(yīng)的結(jié)構(gòu)類型中就可以了。從上一節(jié)的描述可以看到消息的 decoding 過(guò)程也可以通過(guò)幾個(gè)位移操作組成的表達(dá)式計(jì)算即可完成。速度非???。
    image.png

references
google官方文檔

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文轉(zhuǎn)自劉明的分享。原文 簡(jiǎn)介 什么是 Google Protocol Buffer? 假如您在網(wǎng)上搜索,應(yīng)該會(huì)得...
    那樣風(fēng)采閱讀 1,712評(píng)論 0 1
  • 之前在網(wǎng)絡(luò)通信和通用數(shù)據(jù)交換等應(yīng)用場(chǎng)景中經(jīng)常使用的技術(shù)是 JSON 或 XML,而在最近的開發(fā)中接觸到了 Goog...
    401閱讀 503,082評(píng)論 25 379
  • 美與丑是,一念之差。人們可望美好事物,讓人能感受到,生命可貴,人生美麗,人與人之間,互相信任,和溫暖,促進(jìn)社會(huì)和諧...
    一切美好閱讀 830評(píng)論 5 27
  • 1三元運(yùn)算符將自身賦值給一個(gè)變量。 邏輯運(yùn)算符也有選擇的功能。 通過(guò)條件2選1賦值的時(shí)候,三元運(yùn)算符比if語(yǔ)句更加...
    淺兮淺兮閱讀 275評(píng)論 0 0
  • 莫嘆夜雨喇叭聲,變化錯(cuò)愕常相應(yīng)。電驢拖步推沉幕,何妨?長(zhǎng)歌舞袖雨淋淋。
    謙震閱讀 170評(píng)論 0 0

友情鏈接更多精彩內(nèi)容