我的小站,正在持續整理中,歡迎訪問:http://shitouer.cn java
小站博文地址:Google Protocol Buffers 概述 服務器
推薦閱讀順序,但願給你帶來收穫~ 數據結構
《Google Protocol Buffers 概述》 ide
《Google Protocol Buffers 入門》 學習
《Google Protocol Buffers 編碼(Encoding)》 google
Protocol Buffers 是一種輕便高效的結構化數據存儲格式,能夠用於結構化數據串行化,或者說序列化。它很適合作數據存儲或 RPC 數據交換格式。可用於通信協議、數據存儲等領域的語言無關、平臺無關、可擴展的序列化結構數據格式。目前提供了 C++、Java、Python 三種語言的 API。 編碼
本文概述介紹Protocol Buffers,以及開始如何開始Protocol Buffers之旅,本系列主要以Java爲主(雖然超想看Python的,無奈學的還不夠...)。 spa
如下Protocol Buffers簡稱PB。 翻譯
Protocol Buffers提供了一種靈活,高效,自動序列化結構數據的機制,能夠聯想XML,可是比XML更小,更快,更簡單。僅須要自定義一次你所需的數據格式, 而後用戶就可使用Protocol Buffers自動生成的特定的源碼,方便的讀寫用戶自定義的格式化的數據。不限語言,不限平臺。還能夠在不破壞原數據格式的基礎上,依據老的數據格式, 更新現有的數據格式。
在PB中,有一種.proto類型的文件,用戶 在.proto文件中定義PB 「Message」來指定所須要序列化的數據的格式。每個PB Message都是一個小的信息邏輯單元,包含了一些列的name-value對。下面舉例說明一個簡單地.proto文件,他定義了一條包含一個 Person信息的Message:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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;
}
|
如上代碼所示,PB message 格式很是簡單。每種類型的message包含一個或者多個惟一編碼字段,每一個字段由名稱和值類型組成,值類型可使數字(整形或者浮點型),布爾值,字符 串,原始字節,甚至是其餘的PB message。PB容許message中包含message,已達到分層嵌套。能夠定義可選字段,必填字段以及重複字段。想要了解更多如何 寫.proto 文件,能夠訪問:Protocol Buffer Language Guide
定 義好PB message後,選擇合適語言的PB編譯器,編譯.proto文件,就能夠生成存取數據的相關類。這些類包括簡單的設置及讀取字段的方法,也包括對整個 數據結構的message與二進制之間的轉換。舉個例子,若是你使用的語言是java,運行編譯器編譯上例.proto文件後,生成的類中包含一個 Person類。使用該類,就能夠計算,序列化以及檢索PB message。以下代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
public static void main(String[] args)throws IOException {
Person john = Person
.newBuilder()
.setId(1)
.setName("john")
.setEmail("john@youku.com")
.addPhone(
PhoneNumber
.newBuilder()
.setNumber("1861xxxxxxx")
.setType(PhoneType.WORK)
.build())
.build();
FileOutputStream output =new FileOutputStream("abc.txt");
john.writeTo(output);
output.close();
}
|
接下來,你能夠用以下代碼讀取:
1
2
3
4
5
6
7
8
9
10
|
public static void main(String[] args)throws IOException {
FileInputStream input =new FileInputStream("abc.txt");
Person person = Person.parseFrom(input);
System.out.println(person.getId());
System.out.println(person.getName());
System.out.println(person.getEmail());
System.out.println(person.getPhoneCount());
System.out.println(person.getPhone(0).getNumber());
System.out.println(person.getPhone(0).getType());
}
|
PB是易於擴展的,能夠向後兼容的,咱們能夠在PB message中添加新的字段,這樣,在parse的時候,老版本的數據就會簡單的忽略新增長的字段。所以,若是現有通訊協議使用了PB做爲其數據格式,咱們能夠直接擴展該通訊協議,而沒必要擔憂這將會破壞現有的代碼。
對於使用.proto文件生成PB 客戶端代碼,能夠參看這方面的完整教程:API Reference section。想要學習瞭解PB message是如何編碼的,能夠參見:Protocol Buffer Encoding。
若是要序列化結構化數據,比起XML,PB實在是有許多的優勢能夠道道~
假如咱們要模擬一個Person,該對象包含name和email屬性,若是用XML,咱們定義以下:
1
2
3
4
|
<person>
<name>John Doe</name>
<email>jdoe@example.com</email>
</person>
|
對應的,PB以下:
1
2
3
4
|
person {
name:"John Doe"
email:"jdoe@example.com"
}
|
請注意:這裏僅是PB格式的一種直觀表示,真實的PB並不是這樣存儲,實際上,在鏈路中,PB數據時二進制格式的。
當這段數據編碼爲PB二進制格式時,其實際大小大概是28bytes,編碼時間爲100~200納秒。若是用XML的話,即便去除空格,大小也至少爲69bytes,編碼時間大概須要5000~10,000納秒。
一樣,解析這段代碼,PB比XML要方便許多。用PB的話:
1
2
|
person.getName();
person.getEmail();
|
而用XML的話:
1
2
|
personNode.getElementsByTagName("name")
personNode.getElementsByTagName("email")
|
相比起來,PB更直接,並且不須要遍歷節點等XML操做。
可是,金無足赤,人無完人,PB也同樣。對於有不少標籤的,基於文本的數據(例如HTML),XML就完勝PB。XML是子描述的,能夠隨機且交錯讀取讀取文本節點。XML是自描述的,而PB不是,PB必需要有格式定義文件(.proto 文件)
PB由Google開發,最初是用於處理索引服務器的請求/響應協議。在有PB以前,Google使用手動編組和解組的方式來處理請求/相應協議。這種方式須要支持許多版本的協議,這就致使一些代碼很是的醜陋,例如:
1
2
3
4
5
6
7
8
|
if (version ==3) {
...
}else if (version >4) {
if (version ==5) {
...
}
...
}
|
另外,這種顯示格式的協議一樣將新發布的協議版本也搞得很是複雜,由於開發者必須在啓用新的協議以前,確認全部的服務器,包括請求的發起者以及實際處理請求者,他們都可以理解新的協議。
PB即被設計來解決這些問題:
至此,雖然解決了諸多問題,但用戶依然須要手寫他們的解析及編碼代碼。
隨着系統的發展,PB逐漸造成了許多新的特性及用法:
Google Protocol Buffer( 簡稱 Protobuf) 是 Google 公司內部的混合語言數據標準,目前已經正在使用的有超過 48,162 種報文格式定義和超過 12,183 個 .proto 文件。他們用於 RPC 系統和持續數據存儲系統。
譯自:https://developers.google.com/protocol-buffers/docs/overview
初次嘗試翻譯,諸多不夠信達雅之處,還望可以不吝指出不到之處,謝謝~