我的小站,正在持续整理中,欢迎访问:http://shitouer.cn java
小站博文地址:Google Protocol Buffers 概述 服务器
推荐阅读顺序,但愿给你带来收获~ 数据结构
《Google Protocol Buffers 概述》 ide
《Google Protocol Buffers 入门》 学习
《Google Protocol Buffers 编码(Encoding)》 google
Protocol Buffers 是一种轻便高效的结构化数据存储格式,能够用于结构化数据串行化,或者说序列化。它很适合作数据存储或 RPC 数据交换格式。可用于通信协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、Java、Python 三种语言的 API。 编码
本文概述介绍Protocol Buffers,以及开始如何开始Protocol Buffers之旅,本系列主要以Java为主(虽然超想看Python的,无奈学的还不够...)。 spa
如下Protocol Buffers简称PB。 翻译
Protocol Buffers提供了一种灵活,高效,自动序列化结构数据的机制,能够联想XML,可是比XML更小,更快,更简单。仅须要自定义一次你所需的数据格式, 而后用户就可使用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。
若是要序列化结构化数据,比起XML,PB实在是有许多的优势能够道道~
假如咱们要模拟一个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 文件)
PB由Google开发,最初是用于处理索引服务器的请求/响应协议。在有PB以前,Google使用手动编组和解组的方式来处理请求/相应协议。这种方式须要支持许多版本的协议,这就致使一些代码很是的丑陋,例如:
1
2
3
4
5
6
7
8
|
if (version ==3) {
...
}else if (version >4) {
if (version ==5) {
...
}
...
}
|
另外,这种显示格式的协议一样将新发布的协议版本也搞得很是复杂,由于开发者必须在启用新的协议以前,确认全部的服务器,包括请求的发起者以及实际处理请求者,他们都可以理解新的协议。
PB即被设计来解决这些问题:
至此,虽然解决了诸多问题,但用户依然须要手写他们的解析及编码代码。
随着系统的发展,PB逐渐造成了许多新的特性及用法:
Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。他们用于 RPC 系统和持续数据存储系统。
译自:https://developers.google.com/protocol-buffers/docs/overview
初次尝试翻译,诸多不够信达雅之处,还望可以不吝指出不到之处,谢谢~