歡迎來到protocol buffer的開發者指南文檔,一種語言無關、平台無關、擴展性好的用於通信協議、數據存儲的結構化數據序列化方法。
本文檔是面向計划將protocol buffer使用的到自己的Java、C++或Python應用程序中的開發者的。這個概覽介紹了protocol buffer,並告訴你如何開始,你隨后可以跟隨編程指導(https://developers.google.com/protocol-buffers/docs/tutorials )去深入研究protocol buffer編碼方式(https://developers.google.com/protocol-buffers/docs/encoding )。同時API參考文檔(https://developers.google.com/protocol-buffers/docs/reference/overview )也是提供了這三種編程語言的版本,以及可以參考語言指南(https://developers.google.com/protocol-buffers/docs/proto )和樣式指南(https://developers.google.com/protocol-buffers/docs/style )去編寫 .proto 文件。
什么是protocol buffer
ProtocolBuffer是用於結構化數據序列化的靈活、高效、自動的方法,類似XML,不過它更小、更快、也更簡單。你可以定義自己的數據結構,然后使用代碼生成器生成的代碼來讀寫這個數據結構。你甚至可以在無需重新部署程序的情況下更新數據結構。
他們如何工作
你首先需要在一個 .proto 文件中定義你需要做序列化的數據結構信息。每個ProtocolBuffer信息是一小段邏輯記錄,包含一系列的鍵值對。這里有個非常簡單的.proto 文件定義了個人信息:
-
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;
-
}
如你所見,消息格式很簡單,每個消息類型擁有一個或多個特定的數字字段,每個字段擁有一個名字和一個值類型。值類型可以是數字(整數或浮點)、布爾型、字符串、原始字節或者其他ProtocolBuffer類型,還允許數據結構的多層次嵌套。你可以指定可選字段,必選字段和重復字段。你可以在(https://developers.google.com/protocol-buffers/docs/proto )找到更多關於如何編寫.proto 文件的信息。
一旦你定義了自己的報文格式(message),你就可以運行ProtocolBuffer編譯器,將你的.proto 文件編譯成特定語言的類。這些類提供了簡單的方法訪問每個字段(像是name() 和set_name() ),像是訪問類的方法一樣將結構序列化或反序列化。例如你可以選擇C++語言,運行編譯如上的協議文件生成類叫做Person 。隨后你就可以在應用中使用這個類來序列化的讀取報文信息。你可以這么寫代碼:
-
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);
然后,你可以讀取報文中的數據:
-
fstream input("myfile", ios::in | ios::binary);
-
Person person;
-
person.ParseFromIstream(&input);
-
cout << "Name: " << person.name() << endl;
-
cout << "E-mail: " << person.email() << endl;
你可以在不影響向后兼容的情況下隨意給數據結構增加字段,在反序列化的時候,舊有的數據會忽略新的字段。所以如果使用ProtocolBuffer作為通信協議,你可以無須擔心破壞現有代碼的情況下擴展協議。
你可以在API參考(https://developers.google.com/protocol-buffers/docs/reference/overview ) 中找到完整的參考,並且關於ProtocolBuffer的報文格式編碼則可以在(https://developers.google.com/protocol-buffers/docs/encoding )中找到參考。
為什么不用XML?
ProtocolBuffer擁有多項比XML更高級的序列化結構數據的特性,ProtocolBuffer:
· 更簡單
· 小3-10倍
· 快20-100倍
· 更少的歧義
· 可以方便的生成數據存取類
例如,讓我們看看如何在XML中建模Person的name和email字段:
-
<person>
-
<name>John Doe</name>
-
<email>jdoe@example.com</email>
-
</person>
對應的ProtocolBuffer報文則如下:
-
# Textual representation of a protocol buffer.
-
# This is * not* the binary format used on the wire.
-
person {
-
name: "John Doe"
-
email: "jdoe@example.com"
-
}
當這個報文編碼到ProtocolBuffer的二進制格式
(https://developers.google.com/protocol-buffers/docs/encoding )時(上面的文本僅用於調試和編輯),它只需要28字節和100-200ns的解析時間。而XML的版本需要69字節(除去空白)和5000-10000ns的解析時間。
當然,操作ProtocolBuffer也很簡單:
-
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;
當然,ProtocolBuffer並不是在任何時候都比XML更合適,例如ProtocolBuffer無法對一個基於標記文本的文檔建模,因為你根本沒法方便的在文本中插入結構。另外,XML是便於人類閱讀和編輯的,而ProtocolBuffer則不是。還有XML是自解釋的,而ProtocolBuffer僅在你擁有報文格式定義的.proto 文件時才有意義。
聽起來像是我要的解決方案,如何開始?
下載包(https://developers.google.com/protocol-buffers/docs/downloads.html ),包含了Java、Python、C++的ProtocolBuffer編譯器,用於生成你需要的IO類。構建和安裝你的編譯器,按照README的說明進行就可以做到。
一旦你安裝好了,就可以跟着編程指導
(https://developers.google.com/protocol-buffers/docs/tutorials )來選擇語言-隨后就是使用ProtocolBuffer創建一個簡單的應用了。
介紹proto3
我們的最新版本3 alpha (https://github.com/google/protobuf/releases )版本引入了一個新的語言版本- Protocol Buffers語言版本3(又名proto3),以及一些新特性在我們現有的語言版本(又名proto2)。Proto3簡化了Protocol Buffers語言,易用性更高使它可以成為一個廣泛的編程語言。我們目前的alpha版本允許您生成Protocol Buffers代碼在Java、c++、Python、JavaNano,和Ruby。此外您可以生成proto3代碼去使用最新的protoc插件,可以從golang / protobuf Github庫。更多的語言是管道。
我們目前推薦嘗試proto3只有以下情況時使用:
· 如果你想要嘗試使用protocol buffers在我們的一個新支持的語言。
· 如果你想嘗試我們的新開源RPC實現gRPC (http://github.com/grpc/grpc-common )(目前也是alpha版本),我們建議使用所有新gRPC proto3服務器和客戶端,避免兼容性問題。
注意,兩個語言版本的api不是完全兼容。為了避免對現有用戶的不便,我們將在新Protocol Buffers正式版本中繼續支持以前的語言版本。
(如果名字proto2和proto3似乎有點讓人困惑,因為當我們最初開源Protocol Buffers它實際上是google的第二個版本的語言——也稱為proto2。這也是為什么我們的開源版本號從v2.0.0)。
一點歷史
ProtocolBuffer最初是在Google開發的,用以解決索引服務器的請求、響應協議。在使用ProtocolBuffer之前,有一種格式用以處理請求和響應數據的編碼和解碼,並且支持多種版本的協議。而這最終導致了丑陋的代碼,有如:
-
if (version == 3) {
-
...
-
} else if (version > 4) {
-
if (version == 5) {
-
...
-
}
-
...
-
}
通信協議因此變得越來越復雜,因為開發者必須確保,發出請求的人和接受請求的人必須同時兼容,並且在一方開始使用新協議時,另外一方也要可以接受。
ProtocolBuffer設計用於解決這一類問題:
· 很方便引入新字段,而中間服務器可以忽略這些字段,直接傳遞過去而無需理解所有的字段。
· 格式可以自描述,並且可以在多種語言中使用(C++、Java等)
然而用戶仍然需要手寫解析代碼。
隨着系統的發展,它擁有了一些其它的特性和功能:
· 自動生成編碼和解碼代碼,而無需自己編寫解析器。
· 除了用於簡短的RPC(Remote Procedure Call)請求,人們使用ProtocolBuffer來做數據存儲格式(例如BitTable)。
· RPC服務器接口可以作為.proto 文件來描述,而通過ProtocolBuffer的編譯器生成存根(stub)類供用戶實現服務器接口。
ProtocolBuffer現在已經是Google的混合語言數據標准了,現在已經正在使用的有超過48,162種報文格式定義和超過12,183個.proto 文件。他們用於RPC系統和持續數據存儲系統。