Protocol Buffers 开发者指南

欢迎来到 protocol buffers 的开发者指南。protocol buffers 是一个语言中立,平台中立针对通信协议,数据存储和其余领域中对结构化数据进行序列化的扩展方法。html

本文档主要针对的是 Java,C++ 或 Python 的开发人员但愿在开发的应用程序中使用 Protocol Buffers。这个有关 Protocol Buffers 摘要性的介绍将会告诉你如何开始使用 Protocol Buffers。若是你但愿更加深刻的了解有关 Protocol Buffers 的内容,你能够进入 tutorials 或者 protocol buffer encoding 页面来详细了解。ios

有关 API 的参考文档,请参考页面:reference documentation 这里提供了全部这 3 种语言的参考,同时也针对 .proto language 和 style 提供相关的指南。git

什么是 Protocol Buffers?

Protocol buffers 是对结构化数据序列化的一个灵活,高效,自动化工具 —— 你能够将 Protocol buffers 想象成 XML,可是体积更小,更快也更加简单。github

你能够本身定义你的结构化数据,而后你可使用特定的代码生成工具来很是容易对你的结构化数据进行读取和写入。这些数据的读取和写入能够是一系列的数据流和使用不一样的计算机程序语言。你甚至能够在不对已经部署的程序进行破坏的状况下更新你的数据结构。golang

Protocol Buffers 是如何进行工做的

你须要制定你但愿如何将你的数据进行序列化。你是经过 proto 文件来定义你的消息结构化数据的。服务器

每一 protocol buffer message 是一个小的信息记录逻辑,这个消息中包含有一系列的名字,变量对照序列。下面是一些基本的.proto 文件,这些文件中定义了一个消息,这个消息包含有一个 person 信息:数据结构

message Person {ide

  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;

}

经过上面你能够看到这个消息的格式很是简单—— 每个消息类型都有一个或者多个惟一进行编号的字段,每个字段包含有一个名字和变量类型。

变量能够为数字(整形或者浮点型)(numbers),布尔类型(booleans),字符串(strings),原生二进制(raw bytes)甚至其余的 protocol buffer 消息类型,可以容许你分级的结构化你的数据。

你能够将字段指定为可选字段(optional fields),必须字段(required fields)和重复字段(repeated fields)。你能够从下面的 Protocol Buffer Language Guide 页面中找到更多有关 .proto 的定义。

一旦你成功定义了你的消息,你能够针对你使用的语言使用你定义的 .proto 来运行 protocol buffer 编译器(protocol buffer compiler)来生成数据访问类。

针对每个字段,在数据访问类中提供了简单的访问方法(例如 name() 和 set_name())和序列化到原生 2 进制数据和从原生 2 进制数据反序列化的方法。

针对上面的定义,若是你如今使用的是  C++ 语言的话,当你把消息定义进行编译后,你将会获得一个称为 Person 的类。 你可使用这个类在你的应用程序中进行填充数据,对数据进行序列化和从序列化的数据中(protocol buffer 消息)从新得到 Person 数据。

而后你能够写一些相似 Person 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;

你能够向你的消息中添加新的字段而不会损坏老的消息。这是由于在老的消息处理中,针对新的字段是彻底忽略掉的。所以,若是你在你的通信协议中使用 protocol buffers 为数据结构的话,你能够对你的协议和消息进行扩展而不须要担忧老的代码没有办法编译经过,或者损坏老的代码。

你能够访问 API Reference section 页面中的内容来了解完整 protocol buffer 代码的生成和使用。

你也能够在 Protocol Buffer Encoding 页面中了解更多protocol buffer 消息是如何进行编码的。

为何不使用 XML

针对 XML 来讲 Protocol Buffers 具备更多的优点来对序列化结构数据。

  • 更加简单
  • 小于 XML  3 到 10 倍
  • 快于 XML 20 到 100 倍
  • 松耦合
  • 使用程序工具来建立数据访问类,使数访问类更加简单

假设,你须要讲 person 这个数据进行定义,在 XML 你须要使用:

<person>

  <name>John Doe</name>

  <email>jdoe@example.com</email>

</person>

来进行定义。

在 Protocol Buffers 中针对上面的消息文本化(text format)后显示为:

# Textual representation of a protocol buffer.

# This is *not* the binary format used on the wire.

person {

  name: "John Doe"

  email: "jdoe@example.com"

}

当上面的消息被编码为 Protocol Buffer 二进制格式(binary format)上面的文字可能小于 28 bytes,而且可能须要 100-200 纳秒(nanoseconds)来进行处理。

咱们将上面转换为能够人为读取的目的主要是为进行调试和编辑。

若是你使用 XML 的话,上面的信息至少须要 69 bytes (你须要删除全部的空格),同时你须要 5,000-10,000 纳秒(nanoseconds)来进行处理。

同时,对 protocol buffer 进行操做也是很是容易的:

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;

可是,protocol buffers 并非任什么时候候都会比 XML 好。例如,针对基于文本的标记语言(例如,XML),protocol buffers 就不是一个很好的选项,由于你不能使用 protocol buffer 更好的在文档中进行交换。更主要的是 HTML 是人类能够阅读和编辑的。protocol buffer 也不是不能够人为的读取,可是针对原生的 protocol buffer 格式是没有办法人为进行读取和编辑的。

XML 与  HTML 同样,在某种程度上是一种自我描述数据。protocol buffer 只针对你在 .proto 文件中描述的内容进行表达。

看起来像一个解决方案,我应该如何开始呢?

Download the package – 这包中含有针对 Java, Python, 和 C++ protocol buffer 编译器源代码,和你须要进行 I/O 和测试的类。但愿对你的编译器进行编译和构建,请参考代码中的 README 文件。

一旦你完成了全部的设置,请参考 tutorial 页面中的内容来选择你须要的语言——这个可以帮助你使用 protocol buffer 建立一个简单的应用程序。

介绍 proto3

在咱们最新的 version 3 发行版 中推出了新的语言版本 —— Protocol Buffers language version 3(另称 proto3),在这个版本中针对咱们已经存在的语言版本(proto2)使用了一些新的特性。

Proto3 简化了 protocol buffer 语言,使其更加容易使用而且可以支持更多的语言:咱们当前发行的 proto3 可以让你建立 Java, C++, Python, Java Lite, Ruby, JavaScript, Objective-C, and C#。

另外你也能够经过使用 Go protoc 插件来用 proto3 建立 Go 代码,这个插件你能够到 golang/protobuf Github 中下载到。更多的语言还在逐步进行支持中。

请注意,这 2 个版本的 API 并非彻底兼容的。为了照顾还在使用老版本的用户,咱们将会在新的 protocol buffers 发行中同时支持老的版本。

你能够在下面的发行日志(release notes)查看 2 个版本的主要不一样。有关 proto3 的句法,请参考 Proto3 Language Guide 中的内容,针对 proto3 的完整文档尚未编写完成,将会随后推出。

看起来 proto2 和 proto3 可能会产生一些混淆,这是由于原始的开源  protocol buffers 其实是 Google 内部语言的第二个版本,同时咱们的开源版本也是从 v2.0.0 开始的。简单来讲就是 proto 最开始的版本是 Google 内部使用的,在 proto 第二个版本的时候,Google 决定进行开源了,因此开源的 proto 是从 proto2 开始的。

一个简短的历史

Protocol buffers 最开始是在 Google 内部进行开发的,用于处理在索引服务器上请求/响应(request/response)的协议。

在 Protocol buffers 以前,针对请求和响应,使用的是 marshalling/unmarshalling,这个可以支持一系列的协议。可是结果看起来倒是很是的难看,例如:

if (version == 3) {

  ...

else if (version > 4) {

  if (version == 5) {

    ...

  }

  ...

}

明确格式化的的协议也使新版本的协议更加难以推出,这是由于开发者必须可以了解老协议在服务器之间是如何进行处理的,同时也须要了解新的协议。只有对新老协议都有所了解后才能逐步使用新的协议替换老的协议。

Protocol buffers 被用来设计解决上面的不少问题:

  • 新的字段比较可以容易的进行定义,中级服务器不须要对数据进行检查,直接对数据进行处理,同时也能够直接传输数据而不须要了解数据是如何进行定义的。
  • 格式使用自描述,可以更加容易支持更多的语言(C++,Java 等)。

可是,用户仍是须要手动书写他们本身的处理diam。

做为系统的进化来讲,它得到了许多其余的特性和用途:

  • 自动生成序列化和反序列化代码而避免手动书写这些代码。
  • 除了开始使用短时间RPC(远程过程调用)请求,人们开始使用 protocol buffers 做为高效的自描述结构化数据格式(主要针对数据短时间存在,例如在 Bigtable)。
  • 服务器RPC接口开始被声明为协议文件的一部分,协议编译器生成根类,用户能够经过服务器接口的实现和重载它们。

Protocol buffers 在 Google 中成为针对数据的通用语言—— 随着时间的流逝,在 Google 内部已经有超过 348,952 .proto 文件被定义。这些被用在 RPC 系统和存储系统中存储数据。

https://www.cwiki.us/display/ProtocolBuffers/Developer+Guide

相关文章
相关标签/搜索