天天看點

[翻譯]ProtoBuf 官方文檔(一)- 開發者指南開發者指南

翻譯查閱外網資料過程中遇到的比較優秀的文章和資料,一是作為技術參考以便日後查閱,二是訓練英文能力。

此文翻譯自 Protocol Buffers 官方文檔 Developer Guide 部分

翻譯為意譯,不會照本宣科的字字對照翻譯

以下為原文内容翻譯

開發者指南

歡迎使用 protocol buffers 的開發者文檔, protocol buffers 是一種語言無關、平台無關、可擴充的序列化結構資料的方法,它可用于通信協定、資料存儲等。

這篇文檔面向那些希望在自己的應用程式中使用 protocol buffers 的 Java、C++ 或 Python 開發者們。這篇概論(指南)将介紹 protocol buffers 并且告訴你邁出第一步所需要的工作-你之後可以學習具體的 開發教程 或更為深入的學習 protocol buffer 編碼規則。同時我們為所有三種語言都提供了相應的 API 參考文檔,以及編寫 .proto 檔案的文法和風格指南。

protocol buffers 是什麼?

protocol buffers 是一種靈活,高效,自動化機制的結構資料序列化方法-可類比 XML,但是比 XML 更小、更快、更為簡單。你可以定義資料的結構,然後使用特殊生成的源代碼輕松的在各種資料流中使用各種語言進行編寫和讀取結構資料。你甚至可以更新資料結構,而不破壞根據舊資料結構編譯而成并且已部署的程式。

它是如何工作的?

你可以通過在 .proto 檔案中定義 protocol buffer message 類型,來指定你想如何對序列化資訊進行結構化。每一個 protocol buffer message 是一個資訊的小邏輯記錄,包含了一系列的 name-value 對。這裡有一個非常基礎的 .proto 檔案樣例,它定義了一個包含 "person" 相關資訊的 message:

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

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    required string number = 1;
    optional PhoneType type = 2 [default = HOME];
  }

  repeated PhoneNumber phone = 4;
}
           

正如你所見,message 格式很簡單 - 每種 message 類型都有一個或多個具有唯一編号的字段,每個字段都有一個名稱和一個值類型,其中值類型可以是數字(整數或浮點數),布爾值,字元串,原始位元組,甚至(如上例所示)其它 protocol buffer message 類型,這意味着允許你分層次地建構資料。你可以指定 optional 字段,required 字段和 repeated 字段。 你可以在 Protocol Buffer 語言指南 中找到有關編寫

.proto

檔案的更多資訊。

譯者注:

proto3 已舍棄 required 字段,optional 字段也無法顯示使用(因為預設預設就設定為 optional)

一旦定義了 messages,就可以在 .proto 檔案上運作 protocol buffer 編譯器來生成指定語言的資料通路類。這些類為每個字段提供了簡單的通路器(如 name()和 set_name()),以及将整個結構序列化為原始位元組和解析原始位元組的方法 - 例如,如果你選擇的語言是 C++,則運作編譯器上面的例子将生成一個名為 Person 的類。然後,你可以在應用程式中使用此類來填充,序列化和檢索 Person 的 messages。于是你可以寫一些這樣的代碼:

Person person;
person.set_name("John Doe");
person.set_id(1234);
person.set_email("[email protected]");
fstream output("myfile", ios::out | ios::binary);
person.SerializeToOstream(&output);
           

之後,你可以重新讀取解析你的 message

fstream input("myfile", ios::in | ios::binary);
Person person;
person.ParseFromIstream(&input);
cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;
           

你可以在 message 格式中添加新字段,而不會破壞向後相容性;舊的二進制檔案在解析時隻是忽略新字段。是以,如果你的通信協定使用 protocol buffers 作為其資料格式,則可以擴充協定而無需擔心破壞現有代碼。

你可以在 API 參考部分 中找到使用生成的 protocol buffer 代碼的完整參考,你可以在 協定緩沖區編碼 中找到更多關于如何對 protocol buffer messages 進行編碼的資訊。

為什麼不使用 XML?

對于序列化結構資料,protocol buffers 比 XML 更具優勢。Protocol buffers:

  • 更簡單
  • 小 3 ~ 10 倍
  • 快 20 ~ 100 倍
  • 更加清晰明确
  • 自動生成更易于以程式設計方式使用的資料通路類

例如,假設你想要為具有姓名和電子郵件的人模組化。在XML中,你需要:

<person>
    <name>John Doe</name>
    <email>[email protected]</email>
</person>
           

而相對應的 protocol buffer message(參見 protocol buffer 文本格式)是:

# Textual representation of a protocol buffer.
# This is *not* the binary format used on the wire.
person {
  name: "John Doe"
  email: "[email protected]"
}
           

當此消息被編碼為 protocol buffer 二進制格式 時(上面的文本格式隻是為了調試和編輯的友善而用人類可讀的形式表示),它可能是 28 個位元組長,需要大約 100-200 納秒來解析。如果删除空格,XML版本至少為 69 個位元組,并且需要大約 5,000-10,000 納秒才能解析。

此外,比起 XML,操作 protocol buffer 更為容易:

cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;
           

而使用 XML,你必須執行以下操作:

cout << "Name: "
     << person.getElementsByTagName("name")->item(0)->innerText()
     << endl;
cout << "E-mail: "
     << person.getElementsByTagName("email")->item(0)->innerText()
     << endl;
           

但是,protocol buffers 并不總是比 XML 更好的解決方案 - 例如,protocol buffers 不是使用标記(例如 HTML)對基于文本的文檔模組化的好方法,因為你無法輕松地将結構與文本交錯。此外,XML 是人類可讀的和人類可編輯的;protocol buffers,至少它們的原生格式,并不具有這樣的特點。XML 在某種程度上也是自我描述的。隻有擁有 message 定義(.proto檔案)時,protocol buffer 才有意義。

介紹 proto3

我們最新的版本3 release ,它引入了新的語言版本 - Protocol Buffers 語言版本3(又稱 proto3),并且添加了現有語言版本(又稱 proto2)的一些新功能。Proto3 簡化了 Protocol Buffers 語言,既易于使用,又可以在更廣泛的程式設計語言中使用:這個版本允許你使用 Java,C ++,Python,Java Lite,Ruby,JavaScript,Objective-C 和 C# 生成 protocol buffer 代碼。此外,你可以使用最新的 Go protoc 插件為 Go 生成 proto3 代碼,該插件可從 github 庫 golang/protobuf 獲得。更多語言正在籌備中。

請注意,兩種語言版本的 API 不完全相容。為避免給現有使用者帶來不便,我們将繼續在新版本的 protocol buffers 中支援以前的語言版本。

你可以在 發行說明 中看到與目前預設版本的主要差異,并在 Proto3 文法指引 中了解proto3 文法)。proto3 的完整文檔即将推出!

(如果名稱 proto2 和 proto3 看起來有點令人困惑,那是因為當我們最初開源 protocol buffers 時,它實際上是 Google 的第二個語言版本 - 也稱為 proto2。這也是為什麼我們的開源版本從 v2.0.0 開始)。

一點點曆史

Protocol buffers 最初是在 Google 開發的,用于處理索引伺服器請求/響應協定。在 protocol buffer 之前,有一種請求和響應的格式,它手動進行編組/解組,并支援許多版本的協定。這導緻了一些非常醜陋的代碼,例如:

if (version == 3) {
   ...
 } else if (version > 4) {
   if (version == 5) {
     ...
   }
   ...
 }
           

明确格式化的協定也使新協定版本的推出變得複雜,因為開發人員必須確定請求的發起者和處理請求的實際伺服器之間的所有伺服器都能了解新協定,然後才能切換開關以開始使用新協定。

協定緩沖區旨在解決這些問題:

  • 可以輕松引入新字段,中間伺服器不需要檢查資料,可以簡單地解析它并傳遞資料而無需了解所有字段。
  • 格式更具自我描述性,可以用各種語言處理(C ++,Java 等)

但是,使用者仍然需要手寫自己的解析代碼。

随着系統的發展,它獲得了許多其他功能和用途:

  • 自動生成的序列化和反序列化代碼避免了手動解析的需要。
  • 除了用于短期 RPC(遠端過程調用)請求之外,人們還開始使用 protocol buffers 作為一種友善的自描述格式,用于持久存儲資料(例如在 Bigtable 中)。
  • 伺服器 RPC 接口開始被聲明為協定檔案的一部分,protocol 編譯器生成存根類,使用者可以使用伺服器接口的實際實作來覆寫這些類。

Protocol buffers 現在是 Google 的資料通用語言 - 在撰寫本文時,Google 代碼樹中有 12183 個 .proto 檔案,其中一共定義了 48162 種不同的 message 類型。它們既可用于 RPC 系統,也可用于各種存儲系統中的資料持久存儲。

版權聲明

原文連結:https://www.jianshu.com/p/bdd94a32fbd1

繼續閱讀