Google Protocol Buffers 概述


我的小站,正在持續整理中,歡迎訪問:http://shitouer.cn java

小站博文地址:Google Protocol Buffers 概述 服務器

推薦閱讀順序,但願給你帶來收穫~ 數據結構

Google Protocol Buffers 概述ide

Google Protocol Buffers 入門學習

Protocol Buffers 語法指南ui

Google Protocol Buffers 編碼(Encoding)google

1. 概述

Protocol Buffers 是一種輕便高效的結構化數據存儲格式,能夠用於結構化數據串行化,或者說序列化。它很適合作數據存儲或 RPC 數據交換格式。可用於通信協議、數據存儲等領域的語言無關、平臺無關、可擴展的序列化結構數據格式。目前提供了 C++、Java、Python 三種語言的 API。 編碼

本文概述介紹Protocol Buffers,以及開始如何開始Protocol Buffers之旅,本系列主要以Java爲主(雖然超想看Python的,無奈學的還不夠...)。 spa

如下Protocol Buffers簡稱PB。 翻譯

2. Protocol Buffers是什麼

Protocol Buffers提供了一種靈活,高效,自動序列化結構數據的機制,能夠聯想XML,可是比XML更小,更快,更簡單。僅須要自定義一次你所需的數據格式, 而後用戶就可使用Protocol Buffers自動生成的特定的源碼,方便的讀寫用戶自定義的格式化的數據。不限語言,不限平臺。還能夠在不破壞原數據格式的基礎上,依據老的數據格式, 更新現有的數據格式。

3. 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

 4. 爲何不直接使用XML呢?

若是要序列化結構化數據,比起XML,PB實在是有許多的優勢能夠道道~

  1. 更簡單
  2. 比XML小3~10倍
  3. 比XML快20~100倍
  4. 語義定義明確
  5. 自動生成數據存取類,更容易使用

假如咱們要模擬一個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 文件)

 5. 一點歷史

PB由Google開發,最初是用於處理索引服務器的請求/響應協議。在有PB以前,Google使用手動編組和解組的方式來處理請求/相應協議。這種方式須要支持許多版本的協議,這就致使一些代碼很是的醜陋,例如:

1
2
3
4
5
6
7
8
if (version ==3) {
   ...
 }else if (version >4) {
   if (version ==5) {
     ...
   }
   ...
 }

另外,這種顯示格式的協議一樣將新發布的協議版本也搞得很是複雜,由於開發者必須在啓用新的協議以前,確認全部的服務器,包括請求的發起者以及實際處理請求者,他們都可以理解新的協議。

PB即被設計來解決這些問題:

  1. 要能夠很是容易的引入新字段,不須要檢查數據的中間服務器 可以簡單地解析數據,而且無須知道數據全部的字段就能夠傳輸數據。
  2. 格式可以更加的自描述一些,而且能夠被多用語言處理(C ++, Java,Python等)

至此,雖然解決了諸多問題,但用戶依然須要手寫他們的解析及編碼代碼。

隨着系統的發展,PB逐漸造成了許多新的特性及用法:

  1.  自動生成序列化及反序列化代碼,避免手動解析
  2. 除了被用在短生命週期的RPC請求,也開始將PB做爲一種方便的自描述格式去存儲持久化數據。
  3. Server RPC interfaces 開始被聲明爲協議文件的一部分,使用PB compiler 生成stub類,用戶可使用本身實現的服務器接口來覆蓋他們。

Google Protocol Buffer( 簡稱 Protobuf) 是 Google 公司內部的混合語言數據標準,目前已經正在使用的有超過 48,162 種報文格式定義和超過 12,183 個 .proto 文件。他們用於 RPC 系統和持續數據存儲系統。

譯自:https://developers.google.com/protocol-buffers/docs/overview

初次嘗試翻譯,諸多不夠信達雅之處,還望可以不吝指出不到之處,謝謝~

相關文章
相關標籤/搜索