关于protocol buffers的简单说明

来源:互联网 发布:风行家园网络传销案 编辑:程序博客网 时间:2024/05/22 15:32

关于protocol buffers的简单说明


protocol buffers是什么?

Protocol buffers是一个灵活、高效、可以序列化结构数据的自动化机制,这一点和XML很像,但是Protocol buffers体积更小,速度更快、使用更简单。一旦定义了你想要的数据结构,你就可以从不同的数据流、使用不同的语言来生成源代码并且很可以很容易地写和读你所定义的结构化数据。你甚至可以在不破坏已经被编译并部署后的程序的前提下更新数据结构。

 

protocol buffers是如何工作的?

你可以在.proto文件中定义protocol buffer的消息类型(也就是数据结构),来实现你想要的结构化数据的序列化。每一个protocol buffer消息(在.proto文件中定义)都是一条信息的最小的逻辑记录,包含一系列的name-value值对。下面是一个定义.proto文件的基本的例子,在本例中,通过定义.proto文件来描述一个包含了一个关于“人”的消息(也就是关于描述“人”的数据结构)。

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;

}

 

正如你所看到的那样,每个消息类型都有一个或多个编号字段,每个字段都有一个名称和一个数值类型,数值类型可以是数字(整数或浮点数)、布尔值、字符串、原始字节,甚至(如上面的示例中)可以允许你指定可选字段(optional)、必须字段(required)、重复字段(repeated,重复字段里面用来存放多条数据,可以理解为一个数组或者集合)。

一旦你定义好了你的消息结构,你就可以通过protocol buffers编译器基于.proto文件生成相应的数据访问类。这些生成的类为每个字段提供了简单的数据访问接口(如查询),同样也可以序列化并向目标文件写入字节数据或者从数据源读取字节数就并解析。然后,使用编译器生成数据访问类(本例中生成的类为Person),如果你使用的是Java语言,那么可以通过如下方式设置待序列化的数据的字段值:

PersonProbuf.Person.Builder builder = PersonProbuf.Person.newBuilder();

builder.setEmail("zhuxun777@gmail.com");

builder.setId(320324);

builder.setName("Jack Zhu");

然后,你可以通过如下方式获取序列化后的数据:

Person person = builder.build();

byte[] buf = person.toByteArray();

  try {

Person person01 = PersonProbuf.Person.parseFrom(buf);

String strResult = person01.getName() + "," + person01.getId() + "," + person01.getEmail() ;

System.out.println(strResult);

 }

 

你可以将新的字段添加到消息格式中,而不会破坏向后兼容性;旧的二进制文件在解析时会忽略掉新添加的字段。因此如果你有一个使用了protocol buffers数据格式的通信协议,一可以在不破坏现有代码的基础上扩展你的协议。

 

为什么不使用XML?

Protocol buffers在序列化结构数据方面有许多胜过XML的优势,参考如下:

· 使用简单

· XML体积小20~100

· 结构清晰,不会引起歧义

· 相比传统的手动编程来说,protocol buffer可以非常简单的自动生成数据访问类

For example, let's say you want to model a person with a name and an email. In XML, you need to do:

举例来说,如果你用XML格式来定义一个描述包含姓名和email的人的信息时,你需要这样做:

  <person>

    <name>John Doe</name>

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

  </person>

而用protocol buffer 描述的数据如下:

# 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二进制格式(上面的文本只是一个方便人阅读的格式文本,真实表示的并非如此),它可能是28字节长度,大约要用100~200纳秒来解析。而XML格式的消息至少包含69个字节(并且还是在你删除空格的情况下),并且解析时间约为5000~10000纳秒。

读取一个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;

 

总的来说,protobuf的主要特点如下:

1、平台无关、语言无关。
2、二进制、数据自描述。
3、提供了完整详细的操作API。
4、高性能 比xml要快20-100倍
5、尺寸小 比xml要小3-10倍 –高可扩展性
6、数据自描述、前后兼容

适用于

1、不同的平台、系统、语言、模块之间高效的数据交互
2、用于构建大型的复杂系统,降低数据层面的耦合度和复杂度

这里要特别着重说的是protocolBuffer是一种数据协议,就像tcp/ip协议一样,只要是遵守此协议的任何系统之间都能高效的进行数据交互。
第二个特别要说的是 数据自描述。 也就是说拿到任何一个protocolBuffer的数据文件,我们不需要任何其他的辅助信息,就能顺利的解析出其中的数据信息。
这2点是最本质的。
google同时提供了一套代码生成工具,能根据用户自定义的.proto文件,生成c++/java/python的 代码,用于调用protocolBuffer的内核API . 给我们使用提供了很大的便利


如果想了解的更多,可以参考protocol buffer的官方文档:https://developers.google.com/protocol-buffers/docs/overview



3 0