歡迎來到 protocol buffers 的開發者指南。protocol buffers 是一個語言中立,平臺中立針對通訊協議,數據存儲和其他領域中對結構化數據進行序列化的擴展方法。
本文檔主要針對的是 Java,C++ 或 Python 的開發人員希望在開發的應用程式中使用 Protocol Buffers。這個有關 Protocol Buffers 摘要性的介紹將會告訴你如何開始使用 Protocol Buffers。
如果你希望更加深入的了解有關 Protocol Buffers 的內容,你可以進入 tutorials 或者 protocol buffer encoding 頁面來詳細了解。
有關 API 的參考文檔,請參考頁面:reference documentation 這裡提供了所有這 3 種語言的參考,同時也針對 .proto language 和 style 提供相關的指南。
什麼是 Protocol Buffers
Protocol buffers 是對結構化數據序列化的一個靈活,高效,自動化工具 —— 你可以將 Protocol buffers 想像成 XML,但是體積更小,更快也更加簡單。
你可以自己定義你的結構化數據,然後你可以使用特定的代碼生成工具來非常容易對你的結構化數據進行讀取和寫入。這些數據的讀取和寫入可以是一系列的數據流和使用不同的電腦程式語言。
你甚至可以在不對已經部署的程序進行破壞的情況下更新你的數據結構。
Protocol Buffers 是如何進行工作的
你需要制定你希望如何將你的數據進行序列化。你是通過 proto 文件來定義你的消息結構化數據的。
每一 protocol buffer message 是一個小的信息記錄邏輯,這個消息中包含有一系列的名字,變量對照序列。
下面是一些基本的.proto 文件,這些文件中定義了一個消息,這個消息包含有一個 person 信息:
通過上面你可以看到這個消息的格式非常簡單—— 每一個消息類型都有一個或者多個唯一進行編號的欄位,每一個欄位包含有一個名字和變量類型。
變量可以為數字(整形或者浮點型)(numbers),布爾類型(booleans),字符串(strings),原生二進位(raw bytes)甚至其他的 protocol buffer 消息類型,能夠允許你分級的結構化你的數據。
你可以將欄位指定為可選欄位(optional fields),必須欄位(required fields)和重複欄位(repeated fields)。你可以從下面的 Protocol Buffer Language Guide 頁面中找到更多有關 .proto 的定義。
一旦你成功定義了你的消息,你可以針對你使用的語言使用你定義的 .proto 來運行 protocol buffer 編譯器(protocol buffer compiler)來生成數據訪問類。
針對每一個欄位,在數據訪問類中提供了簡單的訪問方法(例如 name() 和 set_name())和序列化到原生 2 進位數據和從原生 2 進位數據反序列化的方法。
針對上面的定義,如果你現在使用的是 C++ 語言的話,當你把消息定義進行編譯後,你將會得到一個稱為 Person 的類。對數據進行序列化和從序列化的數據中(protocol buffer 消息)重新獲得 Person 數據。
然後你可以寫一些類似 Person person; 的代碼。
隨後,你可以對消息進行讀取:
你可以向你的消息中添加新的欄位而不會損壞老的消息。這是因為在老的消息處理中,針對新的欄位是完全忽略掉的。因此,如果你在你的通訊協議中使用 protocol buffers 為數據結構的話,
你可以對你的協議和消息進行擴展而不需要擔心老的代碼沒有辦法編譯通過,或者損壞老的代碼。
你可以訪問 API Reference section 頁面中的內容來了解完整 protocol buffer 代碼的生成和使用。
你也可以在 Protocol Buffer Encoding 頁面中了解更多protocol buffer 消息是如何進行編碼的。
為什麼不使用 XML
針對 XML 來說 Protocol Buffers 具有更多的優勢來對序列化結構數據。
更加簡單
小於 XML 3 到 10 倍
快於 XML 20 到 100 倍
鬆耦合
使用程序工具來創建數據訪問類,使數訪問類更加簡單
假設,你需要講 person 這個數據進行定義,在 XML 你需要使用:
來進行定義。
在 Protocol Buffers 中針對上面的消息文本化(text format)後顯示為:
當上面的消息被編碼為 Protocol Buffer 二進位格式(binary format)上面的文字可能小於 28 bytes,並且可能需要 100-200 納秒(nanoseconds)來進行處理。
我們將上面轉換為可以人為讀取的目的主要是為進行調試和編輯。
如果你使用 XML 的話,上面的信息至少需要 69 bytes (你需要刪除所有的空格),同時你需要 5,000-10,000 納秒(nanoseconds)來進行處理。
同時,對 protocol buffer 進行操作也是非常容易的:
如果使用的是 XML 的話,你需要進行下面的操作:
但是,protocol buffers 並不是任何時候都會比 XML 好。例如,針對基於文本的標記語言(例如,XML),protocol buffers 就不是一個很好的選項,
因為你不能使用 protocol buffer 更好的在文檔中進行交換。更主要的是 HTML 是人類可以閱讀和編輯的。protocol buffer 也不是不可以人為的讀取,但是針對原生的 protocol buffer 格式是沒有辦法人為進行讀取和編輯的。
XML 與 HTML 一樣,在某種程度上是一種自我描述數據。protocol buffer 只針對你在 .proto 文件中描述的內容進行表達。
看起來像一個解決方案,我應該如何開始呢
Download the package – 這包中含有針對 Java, Python, 和 C++ protocol buffer 編譯器原始碼,和你需要進行 I/O 和測試的類。希望對你的編譯器進行編譯和構建,請參考代碼中的 README 文件。
一旦你完成了所有的設置,請參考 tutorial 頁面中的內容來選擇你需要的語言——這個能夠幫助你使用 protocol buffer 創建一個簡單的應用程式。
介紹 proto3
在我們最新的 version 3 發行版 中推出了新的語言版本 —— Protocol Buffers language version 3(另稱 proto3),在這個版本中針對我們已經存在的語言版本(proto2)使用了一些新的特性。
Proto3 簡化了 protocol buffer 語言,使其更加容易使用並且能夠支持更多的語言:我們當前發行的 proto3 能夠讓你創建 Java, C++, Python, Java Lite, Ruby, JavaScript, Objective-C, and C#。
另外你也可以通過使用 Go protoc 插件來用 proto3 創建 Go 代碼,這個插件你可以到 golang/protobuf Github 中下載到。更多的語言還在逐步進行支持中。
請注意,這 2 個版本的 API 並不是完全兼容的。為了照顧還在使用老版本的用戶,我們將會在新的 protocol buffers 發行中同時支持老的版本。
你可以在下面的發行日誌(release notes)查看 2 個版本的主要不同。有關 proto3 的句法,請參考 Proto3 Language Guide 中的內容,針對 proto3 的完整文檔還沒有編寫完成,將會隨後推出。
看起來 proto2 和 proto3 可能會產生一些混淆,這是因為原始的開源 protocol buffers 實際上是 Google 內部語言的第二個版本,同時我們的開源版本也是從 v2.0.0 開始的。
簡單來說就是 proto 最開始的版本是 Google 內部使用的,在 proto 第二個版本的時候,Google 決定進行開源了,所以開源的 proto 是從 proto2 開始的。
一個簡短的歷史
Protocol buffers 最開始是在 Google 內部進行開發的,用於處理在索引伺服器上請求/響應(request/response)的協議。
在 Protocol buffers 之前,針對請求和響應,使用的是 marshalling/unmarshalling,這個能夠支持一系列的協議。但是結果看起來卻是非常的難看,例如:
明確格式化的的協議也使新版本的協議更加難以推出,這是因為開發者必須能夠了解老協議在伺服器之間是如何進行處理的,同時也需要了解新的協議。只有對新老協議都有所了解後才能逐步使用新的協議替換老的協議。
Protocol buffers 被用來設計解決上面的很多問題:
新的欄位比較能夠容易的進行定義,中級伺服器不需要對數據進行檢查,直接對數據進行處理,同時也可以直接傳輸數據而不需要了解數據是如何進行定義的。
格式使用自描述,能夠更加容易支持更多的語言(C++,Java 等)。
但是,用戶還是需要手動書寫他們自己的處理diam。
作為系統的進化來說,它獲得了許多其他的特性和用途:
自動生成序列化和反序列化代碼而避免手動書寫這些代碼。
除了開始使用短期RPC(遠程過程調用)請求,人們開始使用 protocol buffers 作為高效的自描述結構化數據格式(主要針對數據短期存在,例如在 Bigtable)。
伺服器RPC接口開始被聲明為協議文件的一部分,協議編譯器生成根類,用戶可以通過伺服器接口的實現和重載它們。
Protocol buffers 在 Google 中成為針對數據的通用語言—— 隨著時間的流逝,在 Google 內部已經有超過 348,952 .proto 文件被定義。這些被用在 RPC 系統和存儲系統中存儲數據。