Google Protocol Buffers 概述


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

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

推薦閱讀順序,希望給你帶來收獲~

Google Protocol Buffers 概述

Google Protocol Buffers 入門

Protocol Buffers 語法指南

Google Protocol Buffers 編碼(Encoding)

1. 概述

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

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

以下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:

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。如下代碼:

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();
}

接下來,你可以用如下代碼讀取:

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,我們定義如下:

<person>
    <name>John Doe</name>
    <email>jdoe@example.com</email>
</person>

對應的,PB如下:

person {
  name: "John Doe"
  email: "jdoe@example.com"
}

請注意:這里僅是PB格式的一種直觀表示,真實的PB並非這樣存儲,實際上,在鏈路中,PB數據時二進制格式的。

當這段數據編碼為PB二進制格式時,其實際大小大概是28bytes,編碼時間為100~200納秒。如果用XML的話,即使去除空格,大小也至少為69bytes,編碼時間大概需要5000~10,000納秒。

同樣,解析這段代碼,PB比XML要方便許多。用PB的話:

person.getName();
person.getEmail();

而用XML的話:

personNode.getElementsByTagName("name")
personNode.getElementsByTagName("email")

相比起來,PB更直接,而且不需要遍歷節點等XML操作。

但是,金無足赤,人無完人,PB也一樣。對於有很多標簽的,基於文本的數據(例如HTML),XML就完勝PB。XML是子描述的,可以隨機且交錯讀取讀取文本節點。XML是自描述的,而PB不是,PB必須要有格式定義文件(.proto 文件)

 5. 一點歷史

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

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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM