翻譯查閱外網(wǎng)資料過(guò)程中遇到的比較優(yōu)秀的文章和資料黔漂,一是作為技術(shù)參考以便日后查閱驯绎,二是訓(xùn)練英文能力崎场。
此文翻譯自 Protocol Buffers 官方文檔 Developer Guide 部分
翻譯為意譯,不會(huì)照本宣科的字字對(duì)照翻譯
以下為原文內(nèi)容翻譯
開發(fā)者指南
歡迎使用 protocol buffers 的開發(fā)者文檔润绎, protocol buffers 是一種語(yǔ)言無(wú)關(guān)包警、平臺(tái)無(wú)關(guān)撵摆、可擴(kuò)展的序列化結(jié)構(gòu)數(shù)據(jù)的方法,它可用于通信協(xié)議害晦、數(shù)據(jù)存儲(chǔ)等特铝。
這篇文檔面向那些希望在自己的應(yīng)用程序中使用 protocol buffers 的 Java、C++ 或 Python 開發(fā)者們篱瞎。這篇概論(指南)將介紹 protocol buffers 并且告訴你邁出第一步所需要的工作-你之后可以學(xué)習(xí)具體的 開發(fā)教程 或更為深入的學(xué)習(xí) protocol buffer 編碼規(guī)則苟呐。同時(shí)我們?yōu)樗腥N語(yǔ)言都提供了相應(yīng)的 API 參考文檔,以及編寫 .proto 文件的語(yǔ)法和風(fēng)格指南俐筋。
protocol buffers 是什么牵素?
protocol buffers 是一種靈活,高效澄者,自動(dòng)化機(jī)制的結(jié)構(gòu)數(shù)據(jù)序列化方法-可類比 XML笆呆,但是比 XML 更小请琳、更快、更為簡(jiǎn)單赠幕。你可以定義數(shù)據(jù)的結(jié)構(gòu)俄精,然后使用特殊生成的源代碼輕松的在各種數(shù)據(jù)流中使用各種語(yǔ)言進(jìn)行編寫和讀取結(jié)構(gòu)數(shù)據(jù)。你甚至可以更新數(shù)據(jù)結(jié)構(gòu)榕堰,而不破壞根據(jù)舊數(shù)據(jù)結(jié)構(gòu)編譯而成并且已部署的程序竖慧。
它是如何工作的?
你可以通過(guò)在 .proto 文件中定義 protocol buffer message 類型逆屡,來(lái)指定你想如何對(duì)序列化信息進(jìn)行結(jié)構(gòu)化圾旨。每一個(gè) protocol buffer message 是一個(gè)信息的小邏輯記錄,包含了一系列的 name-value 對(duì)魏蔗。這里有一個(gè)非晨车模基礎(chǔ)的 .proto 文件樣例,它定義了一個(gè)包含 "person" 相關(guān)信息的 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 格式很簡(jiǎn)單 - 每種 message 類型都有一個(gè)或多個(gè)具有唯一編號(hào)的字段廓鞠,每個(gè)字段都有一個(gè)名稱和一個(gè)值類型,其中值類型可以是數(shù)字(整數(shù)或浮點(diǎn)數(shù))谣旁,布爾值床佳,字符串,原始字節(jié)榄审,甚至(如上例所示)其它 protocol buffer message 類型夕土,這意味著允許你分層次地構(gòu)建數(shù)據(jù)。你可以指定 optional 字段瘟判,required 字段和 repeated 字段。 你可以在 Protocol Buffer 語(yǔ)言指南 中找到有關(guān)編寫 .proto
文件的更多信息角溃。
譯者注:
proto3 已舍棄 required 字段拷获,optional 字段也無(wú)法顯示使用(因?yàn)槿笔∧J(rèn)就設(shè)置為 optional)
一旦定義了 messages,就可以在 .proto 文件上運(yùn)行 protocol buffer 編譯器來(lái)生成指定語(yǔ)言的數(shù)據(jù)訪問(wèn)類减细。這些類為每個(gè)字段提供了簡(jiǎn)單的訪問(wèn)器(如 name()和 set_name())匆瓜,以及將整個(gè)結(jié)構(gòu)序列化為原始字節(jié)和解析原始字節(jié)的方法 - 例如,如果你選擇的語(yǔ)言是 C++未蝌,則運(yùn)行編譯器上面的例子將生成一個(gè)名為 Person 的類驮吱。然后,你可以在應(yīng)用程序中使用此類來(lái)填充萧吠,序列化和檢索 Person 的 messages左冬。于是你可以寫一些這樣的代碼:
Person person;
person.set_name("John Doe");
person.set_id(1234);
person.set_email("jdoe@example.com");
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 格式中添加新字段纸型,而不會(huì)破壞向后兼容性;舊的二進(jìn)制文件在解析時(shí)只是忽略新字段拇砰。因此梅忌,如果你的通信協(xié)議使用 protocol buffers 作為其數(shù)據(jù)格式,則可以擴(kuò)展協(xié)議而無(wú)需擔(dān)心破壞現(xiàn)有代碼除破。
你可以在 API 參考部分 中找到使用生成的 protocol buffer 代碼的完整參考牧氮,你可以在 協(xié)議緩沖區(qū)編碼 中找到更多關(guān)于如何對(duì) protocol buffer messages 進(jìn)行編碼的信息。
為什么不使用 XML?
對(duì)于序列化結(jié)構(gòu)數(shù)據(jù)瑰枫,protocol buffers 比 XML 更具優(yōu)勢(shì)踱葛。Protocol buffers:
- 更簡(jiǎn)單
- 小 3 ~ 10 倍
- 快 20 ~ 100 倍
- 更加清晰明確
- 自動(dòng)生成更易于以編程方式使用的數(shù)據(jù)訪問(wèn)類
例如,假設(shè)你想要為具有姓名和電子郵件的人建模光坝。在XML中尸诽,你需要:
<person>
<name>John Doe</name>
<email>jdoe@example.com</email>
</person>
而相對(duì)應(yīng)的 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: "jdoe@example.com"
}
當(dāng)此消息被編碼為 protocol buffer 二進(jìn)制格式 時(shí)(上面的文本格式只是為了調(diào)試和編輯的方便而用人類可讀的形式表示),它可能是 28 個(gè)字節(jié)長(zhǎng)教馆,需要大約 100-200 納秒來(lái)解析逊谋。如果刪除空格,XML版本至少為 69 個(gè)字節(jié)土铺,并且需要大約 5,000-10,000 納秒才能解析胶滋。
此外,比起 XML悲敷,操作 protocol buffer 更為容易:
cout << "Name: " << person.name() << endl;
cout << "E-mail: " << person.email() << endl;
而使用 XML究恤,你必須執(zhí)行以下操作:
cout << "Name: "
<< person.getElementsByTagName("name")->item(0)->innerText()
<< endl;
cout << "E-mail: "
<< person.getElementsByTagName("email")->item(0)->innerText()
<< endl;
但是,protocol buffers 并不總是比 XML 更好的解決方案 - 例如后德,protocol buffers 不是使用標(biāo)記(例如 HTML)對(duì)基于文本的文檔建模的好方法部宿,因?yàn)槟銦o(wú)法輕松地將結(jié)構(gòu)與文本交錯(cuò)。此外瓢湃,XML 是人類可讀的和人類可編輯的;protocol buffers理张,至少它們的原生格式,并不具有這樣的特點(diǎn)绵患。XML 在某種程度上也是自我描述的雾叭。只有擁有 message 定義(.proto文件)時(shí),protocol buffer 才有意義落蝙。
介紹 proto3
我們最新的版本3 release 织狐,它引入了新的語(yǔ)言版本 - Protocol Buffers 語(yǔ)言版本3(又稱 proto3),并且添加了現(xiàn)有語(yǔ)言版本(又稱 proto2)的一些新功能筏勒。Proto3 簡(jiǎn)化了 Protocol Buffers 語(yǔ)言移迫,既易于使用,又可以在更廣泛的編程語(yǔ)言中使用:這個(gè)版本允許你使用 Java管行,C ++厨埋,Python,Java Lite捐顷,Ruby揽咕,JavaScript悲酷,Objective-C 和 C# 生成 protocol buffer 代碼。此外亲善,你可以使用最新的 Go protoc 插件為 Go 生成 proto3 代碼设易,該插件可從 github 庫(kù) golang/protobuf 獲得。更多語(yǔ)言正在籌備中蛹头。
請(qǐng)注意顿肺,兩種語(yǔ)言版本的 API 不完全兼容。為避免給現(xiàn)有用戶帶來(lái)不便渣蜗,我們將繼續(xù)在新版本的 protocol buffers 中支持以前的語(yǔ)言版本屠尊。
你可以在 發(fā)行說(shuō)明 中看到與當(dāng)前默認(rèn)版本的主要差異,并在 Proto3 語(yǔ)法指引 中了解proto3 語(yǔ)法)耕拷。proto3 的完整文檔即將推出!
(如果名稱 proto2 和 proto3 看起來(lái)有點(diǎn)令人困惑讼昆,那是因?yàn)楫?dāng)我們最初開源 protocol buffers 時(shí),它實(shí)際上是 Google 的第二個(gè)語(yǔ)言版本 - 也稱為 proto2骚烧。這也是為什么我們的開源版本從 v2.0.0 開始)浸赫。
一點(diǎn)點(diǎn)歷史
Protocol buffers 最初是在 Google 開發(fā)的,用于處理索引服務(wù)器請(qǐng)求/響應(yīng)協(xié)議赃绊。在 protocol buffer 之前既峡,有一種請(qǐng)求和響應(yīng)的格式,它手動(dòng)進(jìn)行編組/解組碧查,并支持許多版本的協(xié)議运敢。這導(dǎo)致了一些非常丑陋的代碼,例如:
if (version == 3) {
...
} else if (version > 4) {
if (version == 5) {
...
}
...
}
明確格式化的協(xié)議也使新協(xié)議版本的推出變得復(fù)雜忠售,因?yàn)殚_發(fā)人員必須確保請(qǐng)求的發(fā)起者和處理請(qǐng)求的實(shí)際服務(wù)器之間的所有服務(wù)器都能理解新協(xié)議传惠,然后才能切換開關(guān)以開始使用新協(xié)議。
協(xié)議緩沖區(qū)旨在解決這些問(wèn)題:
- 可以輕松引入新字段稻扬,中間服務(wù)器不需要檢查數(shù)據(jù)涉枫,可以簡(jiǎn)單地解析它并傳遞數(shù)據(jù)而無(wú)需了解所有字段。
- 格式更具自我描述性腐螟,可以用各種語(yǔ)言處理(C ++,Java 等)
但是困后,用戶仍然需要手寫自己的解析代碼乐纸。
隨著系統(tǒng)的發(fā)展,它獲得了許多其他功能和用途:
- 自動(dòng)生成的序列化和反序列化代碼避免了手動(dòng)解析的需要摇予。
- 除了用于短期 RPC(遠(yuǎn)程過(guò)程調(diào)用)請(qǐng)求之外汽绢,人們還開始使用 protocol buffers 作為一種方便的自描述格式,用于持久存儲(chǔ)數(shù)據(jù)(例如在 Bigtable 中)侧戴。
- 服務(wù)器 RPC 接口開始被聲明為協(xié)議文件的一部分宁昭,protocol 編譯器生成存根類跌宛,用戶可以使用服務(wù)器接口的實(shí)際實(shí)現(xiàn)來(lái)覆蓋這些類。
Protocol buffers 現(xiàn)在是 Google 的數(shù)據(jù)通用語(yǔ)言 - 在撰寫本文時(shí)积仗,Google 代碼樹中有 12183 個(gè) .proto 文件疆拘,其中一共定義了 48162 種不同的 message 類型。它們既可用于 RPC 系統(tǒng)寂曹,也可用于各種存儲(chǔ)系統(tǒng)中的數(shù)據(jù)持久存儲(chǔ)哎迄。
汪
汪