Protocol Buffers 系列 (1) - 什麼是Protocol Buffers?

MurasakiSeiFu發表於2022-05-09

什麼是Protocol Buffers?

Protocol Buffers(協議緩衝區)是一種支援多語言、跨平臺、可擴充套件的機制,用於序列化結構資料格式。相比於XML, JSON, YAML, CSV等一些序列化工具,Protocol Buffers更簡單、更快、更輕量。
我們只需按照我們的意願定義一次資料的結構(message),就可以使用特殊生成的程式碼(可以通過命令列,可以通過Maven外掛),輕鬆地在各種資料流和各種語言之間寫入和讀取我們的結構化資料。

Protocol Buffers解決了什麼問題?

Protocol Buffers為大小高達幾M位元組的結構化資料包提供序列化格式。
通過將 結構化的資料 進行 序列化(序列化),從而實現 資料儲存 / RPC 資料交換的功能
Protocol Buffers可以使用新資訊進行擴充套件,而不會使現有資料無效或要求更新程式碼。

序列化: 將 資料結構或物件 轉換成 二進位制串 的過程
反序列化:將在序列化過程中所生成的二進位制串 轉換成 資料結構或者物件 的過程

Protocol Buffers是 Google 最常用的資料格式。通過.proto字尾的檔案,來編寫Protocol Buffers訊息以及服務。
下面顯示了一個示例訊息:

message Person {
  optional string name = 1;
  optional int32 id = 2;
  optional string email = 3;
}

proto 編譯器在 .proto 檔案構建時被呼叫,以生成各種程式語言的程式碼來操作相應的Protocol Buffers。
每個生成的類都包含每個欄位的簡單訪問器和方法,用於將整個結構序列化和解析為原始位元組。下面展示了一個使用這些生成方法的示例:

Person john = Person.newBuilder()
    .setId(1234)
    .setName("John Doe")
    .setEmail("jdoe@example.com")
    .build();
output = new FileOutputStream(args[0]);
john.writeTo(output);

Protocol Buffers的優點

Protocol Buffers非常適合任何需要以與語言無關、與平臺無關、可擴充套件的方式進行序列化結構化資料的情況。它們通常用於定義通訊協議(與gRPC一起)和資料儲存。

跨語言的相容性

目前Google官方支援C++、C#、Java、Kotlin、PHP、Python、Ruby等,其他的可以在github上找到,支援外掛的方式。

跨專案支援

通過在.proto檔案中自定義message,我們可以跨專案使用Protocol Buffers,同時可以將檔案放置在專案的程式碼庫之外,比如可以和Java資料夾同目錄。
如果我們期望定義將在直接團隊之外廣泛使用的訊息型別或列舉時,我們可以將它們放在自己的檔案中,而不依賴它們。

支援不更新程式碼的情況下更新Proto定義

Protocol Buffers不適用的場景

  • Protocol Buffers 傾向於將訊息一次性的載入記憶體中,並且不會比物件圖大。當我們資料達到數M位元組的時候,需要考慮其他方案,因為在處理較大的資料時,由於序列化副本的原因,最終我們會得到資料的多個副本,會導致記憶體使用量激增,因為建議最好不要超過1M。

    物件圖(Object graph)可以簡單理解為物件之間存在引用關係而組成的關係網。在Java中,垃圾收集器基本上使用物件圖來確定記憶體中哪些例項仍然連結到某個物件,並且程式可能需要這些例項,哪些例項不再可訪問,因此可以刪除。
  • 當Protocol Buffers序列化時,相同的資料可以有許多不同的二進位制序列化。如果不完全解析兩條訊息,就無法比較它們是否相等。
  • 訊息不會被壓縮。
  • 對於涉及大型多維浮點數陣列的許多科學和工程應用,Protocol Buffers訊息在大小和速度上都沒有達到最大效率。對於這些應用程式,FITS和類似格式的開銷更小。
  • Protocol Buffers訊息本身並不自我描述其資料的能力,但它們具有完全反射的模式,您可以使用它來實現自我描述。也就是說,如果不訪問其相應的 .proto 檔案,您將無法完全解釋它。

總結成圖:

Protocol Buffers如何工作?

下圖顯示瞭如何使用協議緩衝區處理資料。

protocol處理資料

序列化速度快
  • 編碼 / 解碼 方式簡單,通過為位運算來完成。
  • 採用PB自身的框架程式碼和編譯器共同完成
序列化體積小
  • 採用了獨特的編碼方式,如Varint、Zigzag編碼方式等等
  • 採用T - L - V 的資料儲存方式:減少了分隔符的使用 & 資料儲存得緊湊

參考:
Protocol Buffers概述

相關文章