Protobuf 從入門到實戰


簡介

      從第一次接觸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協議進行數據數據傳輸的例子,工作流程如下圖:(圖下方深色部分為服務端部分,上方淺色部分為客戶端部分)

 

PB協議工作流程 (2)

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 數據進行序列化、反序列化操作)。

     和其它數據協議的比較如下圖:

image

 

為什么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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM