簡介
從第一次接觸Protobuf到實際使用已經有半年多,剛開始可能被它的名字所唬住,其實就它是一種輕便高效的數據格式,平台無關、語言無關、可擴展,可用於通訊協議和數據存儲等領域。
優點
- 平台無關,語言無關,可擴展;
- 提供了友好的動態庫,使用簡單;
- 解析速度快,比對應的XML快約20-100倍;
- 序列化數據非常簡潔、緊湊,與XML相比,其序列化之后的數據量約為1/3到1/10。
使用詳解
1、服務器安裝
安裝依賴的庫: autoconf automake libtool curl make g++ unzip
安裝:
1 $ ./autogen.sh 2 $ ./configure 3 $ make 4 $ make check 5 $ sudo make install
2、 安卓客戶端安卓
下載相應版本jar包即可。(csdn上上傳了nano版本的jar包和exe文件)
3、 項目實戰
首先舉一個服務端和客戶端按照Protobuf協議進行數據數據傳輸的例子,工作流程如下圖:(圖下方深色部分為服務端部分,上方淺色部分為客戶端部分)
1、服務端和客戶端約定他們使用PB協議作為數據傳輸和存儲的工具,並約定傳輸信息的字段,如下:里面定義支付傳輸的字段。
1 syntax = "proto2"; // PB協議版本 2 import "Common.proto"; // 引入Common.proto,位於Protobuf sdk中 3 4 option optimize_for = LITE_RUNTIME; 5 6 option java_package = "com.xxxx.entity.pb"; // 生成類的包名 7 option java_outer_classname = "PayInfo"; // 生成類的類名 8 9 message PayInfo{ 10 required string payid = 1; // 支付相關的字段信息 11 optional string goodinfo = 2; // optional 為可選參數 12 required string prepayid = 3; // required為必填參數 13 optional string mode = 4; 14 optional int userid = 5; 15 repeated string extra = 6; // repeated 為數組 16 }
2、通過Protobuf源碼編譯得到可運行程序(也可以在網上查找下載,注意PB協議的版本)。得到exe程序中,在windows環境下通過命令行窗口命令生成上述文件中定義的PayInfo.java文件。(protoc 為可執行的exe文件)
1 protoc --java_out ./ ./PayInfo.proto
3、將生成PayInfo文件集成到項目代碼中,同時需要引入 ProtoBuf的sdk(因為生成的PayInfo.Java類中引入了sdk中的類),可以在github上下載:https://github.com/google/protobuf。
4、服務端通過支付信息初始化PayInfo類,並調用ProtoBufSDK中 com.google.protobuf.nano 類的 toByteArray()方法將PayInfo轉化為字節數組,通過網絡傳輸給客戶端(可以進行加密和壓縮操作,注意順序)。
1 public static final byte[] toByteArray(MessageNano msg) { 2 byte[] result = new byte[msg.getSerializedSize()]; 3 toByteArray(msg, result, 0, result.length); 4 return result; 5 }
5、客戶端拿到字節數據后,通過集成的PayInfo.java文件對字節數據解析成PayInfo對象(通過程序生成的java文件都會自動生成這個函數)。
1 public static PayInfo parseFrom(byte[] data)
自此:客戶端就順利拿到了服務端發送的支付信息,可以通過他們調起支付寶或者微信客戶端發起支付了。
由此可以看出ProtoBuf只是一種協議,一種存儲數據的格式,對應上面生成的字節數據的格式,任何語言的程序都可以通過本地類和jar包將字節數據解析成對象(語言/平台無關)。
使用建議:
1、通過編譯程序生成.java文件有不同的版本,建議使用nano版本(3.0之后的PB協議才發布該版本),這種版本生成的java文件方法數較少(沒有set,get等函數),對APK的體積影響更小(四五個文件大前后相差80~90Kb,項目中后續作了替換)。命令:
1 protoc_3.1.0.exe --javanano_out ./ ./GetConfig.proto
2、不管用2.0還是3.0還是nano版本還是非精簡版最終生成的字節數據文件是相同的,不影響前后端的交互。
與其它數據協議比較
Protobuf 有如 XML,不過它更小、更快、也更簡單。你可以定義自己的數據結構,然后使用代碼生成器生成的代碼來讀寫這個數據結構。Protobuf 語義更清晰,無需類似 XML 解析器的東西(因為 Protobuf 編譯器會將 .proto 文件編譯生成對應的數據訪問類以對 Protobuf 數據進行序列化、反序列化操作)。
和其它數據協議的比較如下圖:
為什么Protobuf作為數據傳輸協議如此高效?
1. 數據小:
a) 同json相比較,它不需要傳遞key值,而是用第幾個元素成員變量來表示(而且index使用varient來存儲,只占用一個字節)。
b) 它還會開辟一個字節存放 該字符串的長度,用於直接查找字符串。
c) 不需要傳輸','/‘:’等不必要的分隔符,存儲沒有浪費。
其存儲格式如下:
2. 解析速度快:
json解析成對象的話,需要將每個成員變量的key值到整個json串中匹配查找key。而在protobuf中直接通過比較tag序列就可以了,而且值的獲取也可以直接通過legth獲取,所以解析速度非常快。
參考:
https://developers.google.com/protocol-buffers/
https://www.ibm.com/developerworks/cn/linux/l-cn-gpb/
https://tech.meituan.com/serialization_vs_deserialization.html