一、Protobuf工具介绍
Google Protocol Buffer(简称 Protobuf)是一种轻便高效的结构化数据存储格式,它与平台、语言无关,可扩展,
一般用于通讯协议和数据存储等领域。
相对于其他数据交互格式(如xml和json),protobuf具有以下特点:
1)体积小,更加适合网络传输;
2)支持多语言;
3)消息格式升级和兼容性还不错;
4)序列化反序列化速度非常快;
因此,在实际应用中,protobuf更加适合对响应速度要求更高的数据传输场景。
二、Protobuf安装
2.1 Linux下安装Protobuf
# 下载Protobuf工具包
$ git clone https://github.com/protocolbuffers/protobuf.git
# 安装其他依赖包
$ sudo apt-get install autoconf automake libtool curl make g++ unzip libffi-dev -y
# 安装完成后,进入protobuf目录
$ cd protobuf
# 执行命令
$ ./autogen.sh
$ ./configure
$ make
$ sudo make install
$ sudo ldconfig
$ protoc -h
安装成功后,获取Go语言的Protobuf库。
$ go get -v -u github.com/golang/protobuf/proto
如果获取失败,可以在https://github.com/golang/protobuf手动下载压缩文件,然后解压缩到$GOPATH/src/github.com/golang/目录下。
最后,执行以下命令安装protoc-gen-go插件。
# 进入protoc-gen-go目录
$ cd $GOPATH/src/github.com/golang/protobuf/protoc-gen-go/
# 编译后生成protoc-gen-go可执行文件
$ go build
# 将生成protoc-gen-go可执行文件拷贝到/bin目录下
$ sudo cp protoc-gen-go /bin/
2.2 Windows下安装Protobuf
第一步:下载Protobuf(https://github.com/google/protobuf/releases)。下载完成后家压缩到磁盘任意目录下,并设置PATH环境变量。变量值为Protobuf安装目录下bin目录的路径。
设置成功后,打开命令窗口命令protoc --version查看版本确认是否安装成功。如果能够版本信息代表安装成功。
第二步:下载proto和protoc-gen-go工具。
go get -u github.com/golang/protobuf/proto
go get -u github.com/golang/protobuf/protoc-gen-go
如果因为国内网络问题导致上面命令执行失败,可以通过设置代理解决:go env -w GOPROXY=https://goproxy.cn,direct
第三步:在$GOPATH/src目录下新建一个文件夹,然后在文件夹中创建一个test.proto文件。
syntax = "proto3";
message Test {
string name = 1;
int32 height = 2;
repeated int32 weight = 3;
string motto = 4;
}
第六步:编译文件。
protoc --go_out=./ test.proto
编译成功后,在grpc目录下生成test.pb.go的go文件。
三、第一个Hello World
第一步:在$GOPATH/src目录下创建一个文件夹。
$ cd $GOPATH/src
$ mkdir myproto
第二步:新建proto文件。
syntax = "proto3";
message Test {
string name = 1;
int32 height = 2;
repeated int32 weight = 3;
string motto = 4;
}
第三步:执行编译命令。
$ protoc --go_out=./ *.proto
go_out参数指定编译后文件的输出目录。*.proto指定了对当前文件夹下的所有proto文件进行编译。
编译完成后,在当前文件夹下生成一些xxx.pb.go文件。
四、Protobuf基本语法
(1)文件格式
syntax = "proto3";
message 消息名 {
消息类型定义...
}
第一行指定了使用的proto语法。如果没有指定,默认为proto2。
每一个message消息里面都可以定义多个消息类型。定义消息类型的格式如下:
消息类型 变量名 = 序号;
例如:
string name = 1;
int32 height = 2;
repeated int32 weight = 3;
上面每一行定义一个消息类型。一个消息可以定义多个消息类型。其中,repeated关键字表示重复的意思。在Go语言中代表切片。
注意:类型定义后面的数字不是变量的值。它只是代表一个序号。第一个类型定义的序号为1,第二个类型定义的序号为2,以此类推。
(2)消息类型
Protobuf Type | 描述 | Go Type |
---|---|---|
double | float64 | |
float | float32 | |
int32 | 使用变长编码,对于负值的效率很低。如果你的域有可能是负值,请使用sint64代替 | int32 |
uint32 | 使用变长编码 | uint32 |
uint64 | 使用变长编码 | uint64 |
sint32 | 使用变长编码 | int32 |
sint64 | 使用变长编码 | int64 |
fixed32 | 固定4个字节的长度 | uint32 |
fixed64 | 固定8个字节的长度 | uint64 |
sfixed32 | 固定4个字节的长度 | int32 |
sfixed64 | 固定8个字节的长度 | int64 |
bool | bool | |
bytes | []byte |
(3)定义注释
Protobuf可以使用C/C++/java/Go风格的双斜杠(//)。
(4)默认值
当一个消息被解析的时候,如果被编码的消息不包含一个特定元素,被解析的对象对应的域就会被设置为一个默认值。对于不同的消息类型,默认值也不一样。例如:
- 对于string,默认值为一个空的string
- 对于数值,默认值为0
- 对于bool,默认值为false
- 对于bytes,默认值为空的bytes
除此以外,也可以使用其他消息作为字段的消息类型。例如:
message PetInfo {
string name = 1;
string color = 2;
}
message PersonInfo {
string name = 1;
int32 age = 2;
PetInfo pet = 3;
}
注意:proto3消息中使用proto2消息类型是允许的,反之亦然。但是proto2枚举不可以在proto3中使用。
(5)定义服务
如果要将消息类型在RPC系统中使用,那么在proto文件中需要定义一个RPC的服务接口。Protobuf编译器会根据所选择的不同语言生成服务接口的代码和存根。
例如:定义一个服务,该服务具有一个方法。该方法能够接收一个Request参数,并返回一个Response。此时的proto文件定义如下所示:
# 命令格式:
service 服务名 {
rpc 方法名(参数名) returns (返回参数);
}
例如:
service SearchService {
rpc Search(SearchRequest) returns (SearchResponse);
}
后面我们会结合GRPC给大家演示如何服务定义,以及如何远程调用定义好的服务。