跨平臺(tái)的結(jié)構(gòu)化數(shù)據(jù)傳輸協(xié)議一般情況下關(guān)注三要素和三件事:
- 三要素
- protocal
- 數(shù)據(jù)
- API
- 三件事
- 協(xié)議編譯
- 序列化
- 反序列化
以下三種協(xié)議按照以上要素進(jìn)行介紹
json(javascript object notation)
- 三要素
- protocal:面向javascript,使用eval()自動(dòng)轉(zhuǎn)換成遠(yuǎn)程的對(duì)象,面向其他語(yǔ)言需要自己編寫model并解析
- 數(shù)據(jù):包含多種數(shù)據(jù)類型,對(duì)象(字典表示法),數(shù)組(同質(zhì)化元素集合),string(基本類型,可以用來(lái)作為鍵或者值),nil(空)等
- API:引入json的包,可以提供建立json對(duì)象,讀入(從網(wǎng)絡(luò)或者本地)json數(shù)據(jù),寫出(網(wǎng)絡(luò)或者本地)json數(shù)據(jù)的接口,并且提供顯式類型轉(zhuǎn)換的接口
- 三件事
- 協(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ì)象
- 特性
- 因?yàn)閾碛凶悦枋鲂裕⑶乙晕谋痉绞絺鬏敂?shù)據(jù),所以可擴(kuò)展,可編輯
- 擁有良好的跨平臺(tái)和跨語(yǔ)言特性(提供不同的庫(kù))
- 使用范圍較廣,支持的應(yīng)用場(chǎng)景較為豐富,靈活的語(yǔ)法可以傳輸更廣泛的數(shù)據(jù)
- 文本傳輸,沒(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的概念
- 三要素:
- 協(xié)議:編寫proto文件,類似于java和c++的類定義,但是更具有通用性(提供各種面向語(yǔ)言的編譯庫(kù)),并且采用編號(hào)預(yù)處理
- 數(shù)據(jù):提供更加豐富的數(shù)據(jù)類型,基本可以和高級(jí)語(yǔ)言一一對(duì)應(yīng)
- API: 根據(jù)平臺(tái)提供各種數(shù)據(jù)處理的api,同時(shí)根據(jù)proto文件產(chǎn)生特定的api
- 三件事
- 協(xié)議編譯:編寫proto文件,編譯器自動(dòng)編譯,產(chǎn)生特定語(yǔ)言的類型
- 序列化:一切建立在proto生成的類型之上,建立對(duì)象,采用數(shù)組形式或者api方式寫入數(shù)據(jù),由庫(kù)直接序列化成二進(jìn)制文件,所以相關(guān)數(shù)據(jù)不可編輯;
- 反序列化:讀入對(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)

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


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官方文檔


