什么是protocol buffers
Protocol buffers是Google的与语言无关、平台无关、可扩展的序列化结构数据,比xml更小、更简单、更快。
用户定义数据的结构,通过特殊生成的代码,然后就可以使用多种语言(包括C++、C#、Dart、Go、Java、Python)来读写结构化数据了。
使用protocol buffers
这里以Go为例来进行演示,其他语言请查询官方文档,本例使用proto3版本。
具体包括以下三步:
- 定义message格式的.proto文件
- 使用protocol buffer编译器
- 使用Go protocol buffer API来读写message
定义protocol格式
.proto文件的定义比较简单:为每个想序列化的数据结构新增一个message,并给与每一个field一个名字和类型。为了防止命名冲突.proto文件以包声明开始。如下所示:
1 | syntax = "proto3"; |
其后定义message:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25message Person {
string name = 1;
int32 id = 2; // Unique ID number for this person.
string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
string number = 1;
PhoneType type = 2;
}
repeated PhoneNumber phones = 4;
google.protobuf.Timestamp last_updated = 5;
}
// Our address book file is just one of these.
message AddressBook {
repeated Person people = 1;
}
一个message包含一系列值类型。很多简单的标准数据类型在.proto文件中是可以使用的,其中包括bool
、int32
、float
、double
、string
。当然还有其他的类型,可以参考
在上面的例子中,Person
包含PhoneNumber
,AddressBook
包含Person
,我们可以嵌套定义message类型,如PhoneNumber
就是嵌套在Person
中定义,可以定义枚举类型,如PhoneType
。
每个元素的”=1”,”=2”标签是二进制编码后的唯一标识,1-15标签需要的编码数比15以后的数据要少一个byte,所以一种常用的优化方式是用1-15来标记常用的元素和重复的元素(数组),16以后的tags来标记使用频率少的元素。重复field中的每个元素都需要重新编码,比如PhoneNumber
内tags重现从1开始,所以重复field也是一种常规的优化方法。
如果一个field值没有定义,一般会有默认值:numeric类型的默认值为0,strings类型的默认值是空字符串,bools类型是false,嵌套的messages默认值为”default instance”或者”prototype”,是没有元素的。
如果一个field是repeated的,这个field可以重复若干次。它在protocal buffer中的顺序将保留。可以将其理解为动态大小的数组。
编译protocol buffers
在上面的步骤中,我们得到了AddressBook.proto
文件,现在我们来完成.proto文件的编译:
下载编译器
在linux中的安装如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15# 下载
wget https://github.com/protocolbuffers/protobuf/releases/download/v3.6.1/protobuf-all-3.6.1.tar.gz
# 解压
tar xvf protobuf-all-3.6.1.tar.gz
cd protobuf-3.6.1/
# 生成configure
./autogen.sh
# 编译安装
./configure
make
make check
make install
注意:./autogen.sh时可能报错,请确保安装了automake
,对于未安装的请执行apt-get install automake
或者yum install automake
,遇到libtoolize
报错,请安装apt-get install libtool*
或者yum install libtool*
。遇到报错:1
protoc: error while loading shared libraries: libprotoc.so.17: cannot open shared object file: No such file or directory
将/usr/local/lib加到环境变量中:1
export LD_LIBRARY_PATH=/usr/local/lib
安装结束后可以使用protoc --version
查看protoc版本。
windows的protoc更为简单:
下载windows版的protoc:protoc-3.6.1-win32.zip,解压后将解压目录加到环境变量中,即可。可以运行protoc --version
查看protoc版本。
安装Go protocol buffers插件
运行:1
go get -u github.com/golang/protobuf/protoc-gen-go
运行结束后可以在$GOPATH/bin中看到protoc-gen-go
文件。
编译.protoc文件
在当前AddressBook.proto
文件目录中,运行:1
protoc --go_out=. AddressBook.proto
运行结束后,会在本地生成AddressBook.pb.go文件。
1 | > 详细命令的protoc: |
Protocol Buffer API
1 | package main |
参考
https://developers.google.com/protocol-buffers/
https://developers.google.com/protocol-buffers/docs/tutorials