protocol buffer開發指南(官方)


歡迎來到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 文件定義了個人信息:

 

  1.  
    message Person {
  2.  
    required string name = 1;
  3.  
    required int32 id = 2;
  4.  
    optional string email = 3;
  5.  
     
  6.  
    enum PhoneType {
  7.  
    MOBILE = 0;
  8.  
    HOME = 1;
  9.  
    WORK = 2;
  10.  
    }
  11.  
     
  12.  
    message PhoneNumber {
  13.  
    required string number = 1;
  14.  
    optional PhoneType type = 2 [default = HOME];
  15.  
    }
  16.  
     
  17.  
    repeated PhoneNumber phone = 4;
  18.  
    }

 

  如你所見,消息格式很簡單,每個消息類型擁有一個或多個特定的數字字段,每個字段擁有一個名字和一個值類型。值類型可以是數字(整數或浮點)、布爾型、字符串、原始字節或者其他ProtocolBuffer類型,還允許數據結構的多層次嵌套。你可以指定可選字段,必選字段和重復字段。你可以在(https://developers.google.com/protocol-buffers/docs/proto )找到更多關於如何編寫.proto 文件的信息。

 

 

  一旦你定義了自己的報文格式(message),你就可以運行ProtocolBuffer編譯器,將你的.proto 文件編譯成特定語言的類。這些類提供了簡單的方法訪問每個字段(像是name() 和set_name() ),像是訪問類的方法一樣將結構序列化或反序列化。例如你可以選擇C++語言,運行編譯如上的協議文件生成類叫做Person 。隨后你就可以在應用中使用這個類來序列化的讀取報文信息。你可以這么寫代碼:

 

  1.  
    Person person;
  2.  
    person.set_name( "John Doe");
  3.  
    person.set_id( 1234);
  4.  
    person.set_email( "jdoe@example.com");
  5.  
    fstream output("myfile", ios::out | ios::binary);
  6.  
    person.SerializeToOstream(&output);

 

 

然后,你可以讀取報文中的數據:

 

  1.  
    fstream input("myfile", ios::in | ios::binary);
  2.  
    Person person;
  3.  
    person.ParseFromIstream(&input);
  4.  
    cout << "Name: " << person.name() << endl;
  5.  
    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字段:

  1.  
    <person>
  2.  
    <name>John Doe</name>
  3.  
    <email>jdoe@example.com</email>
  4.  
    </person>

 

對應的ProtocolBuffer報文則如下:

  1.  
    # Textual representation of a protocol buffer.
  2.  
    # This is * not* the binary format used on the wire.
  3.  
    person {
  4.  
    name: "John Doe"
  5.  
    email: "jdoe@example.com"
  6.  
    }

 

當這個報文編碼到ProtocolBuffer的二進制格式

(https://developers.google.com/protocol-buffers/docs/encoding )時(上面的文本僅用於調試和編輯),它只需要28字節和100-200ns的解析時間。而XML的版本需要69字節(除去空白)和5000-10000ns的解析時間。

 

 

當然,操作ProtocolBuffer也很簡單:

  1.  
    cout << "Name: " << person.name() << endl;
  2.  
    cout << "E-mail: " << person.email() << endl;

 

而XML的你需要:

  1.  
    cout << "Name: "
  2.  
           << person.getElementsByTagName( "name")->item(0)->innerText()
  3.  
           << endl;
  4.  
    cout << "E-mail: "
  5.  
           << person.getElementsByTagName( "email")->item(0)->innerText()
  6.  
           << 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之前,有一種格式用以處理請求和響應數據的編碼和解碼,並且支持多種版本的協議。而這最終導致了丑陋的代碼,有如:

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

通信協議因此變得越來越復雜,因為開發者必須確保,發出請求的人和接受請求的人必須同時兼容,並且在一方開始使用新協議時,另外一方也要可以接受。

 

ProtocolBuffer設計用於解決這一類問題:

· 很方便引入新字段,而中間服務器可以忽略這些字段,直接傳遞過去而無需理解所有的字段。

· 格式可以自描述,並且可以在多種語言中使用(C++、Java等)

 

然而用戶仍然需要手寫解析代碼。

 

隨着系統的發展,它擁有了一些其它的特性和功能:

· 自動生成編碼和解碼代碼,而無需自己編寫解析器。

· 除了用於簡短的RPC(Remote Procedure Call)請求,人們使用ProtocolBuffer來做數據存儲格式(例如BitTable)。

· RPC服務器接口可以作為.proto 文件來描述,而通過ProtocolBuffer的編譯器生成存根(stub)類供用戶實現服務器接口。

 

ProtocolBuffer現在已經是Google的混合語言數據標准了,現在已經正在使用的有超過48,162種報文格式定義和超過12,183個.proto 文件。他們用於RPC系統和持續數據存儲系統。

參考:protocol buffer開發指南(官方)


免責聲明!

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



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