01
介绍
在学习 gRPC 之前,我们需要先了解 Protocal Buffers,也就是 protobuf,它是接口设计语言(IDL),它与编程语言无关,可以生成所有主流编程语言的代码,而且,它是二进制格式的数据,比较适合传递大量的数据。
在编写 gRPC 代码之前,首先使用 protobuf 定义服务端和客户端之间传递的消息(message)和 gRPC 服务(service),然后安装需要用到的库,使用命令行工具自动生成 gRPC 的代码。
02
protobuf 语法
protobuf 文件是以 .proto
后缀名结尾,一般会在文件开头声明 proto 的版本,syntax = "proto3";
,如果不声明,则默认使用 proto2 版本。
接下来,我们就可以开始定义消息(message),使用关键字 message
,message User {}
,然后在大括号中定义字段。
示例代码:
代码语言:javascript复制message User {
int64 id = 1;
string name = 2;
}
阅读上面这段代码,我们发现定义字段的格式是数据类型,字段名和编号(tag),tag 可以使用的数字范围是 1~536,870,911
,但是不能使用 19000~19999
之间的数字,这部分数字是保留编号。
另外,编号 1~15
占用 1 个字节,所以建议用在使用频繁的字段上,编号 16~2047
占用 2 个字节,建议用在使用不频繁的字段上。
03
protobuf 数据类型
protobuf 数据类型包含标量类型和复合类型,其中标量类型包含以下几种:
- 数值,包含
double
,float
,int32
,int64
,uint32
,uint64
,sint32
,sint64
,fixed32
,fixed64
,sfixed32
,sfixed64
。 - 布尔 bool
- 字符串 string
- 字节 bytes
04
protobuf 字段规则
protobuf 字段规则有两个,单数(singular)和复数(repeated),必须满足其中一个,proto3 默认字段规则是单数。单数的意思是该字段只能出现 0 或 1 次,也可以理解为可选字段,如果出现 0 次,该字段的值是类型零值;复数是包含该字段类型任意数量元素的数组,在 Golang 中是该字段类型的切片。
示例代码:
代码语言:javascript复制message User {
int64 id = 1;
string name = 2;
repeated string emails = 3;
}
05
protobuf 字段变更
在应用程序开发中,可能会遇到字段修改或删除,protobuf 不允许修改字段的编号(tag),但是可以删除字段,前提是被删除的字段的编号不再被其他字段使用,一般有两种方式,一种是在需要删除的字段名前添加前缀 OBSOLETE_
,而不是删除该字段;另一种方式是把需要删除的字段的编号(tag)使用关键字 reserved
保留,避免被其他字段使用被删除字段的编号(tag)。
关键字 reserved
除了可以保留字段编号之外,还可以保留字段名称,可用于设置禁用字段名。
示例代码:
代码语言:javascript复制message User {
int64 id = 1;
string name = 2;
// repeated string emails = 3;
reserved 3, 16 to 100, 200 to max;
reserved "uid", "uname";
}
06
protobuf 定义包名
在应用程序开发中,多个 proto 文件可能会存在相同的消息(message),我们可以使用包名做区分。
示例代码:
代码语言:javascript复制// 定义包名
package user;
// 定义 golang 包名
option go_package = "userpb";
07
protobuf 嵌套和导入
如果定义的 message 包含一些可以复用的字段,我们可以使用嵌套的方式,将可被复用的字段单独定义为 message,然后嵌套在需要使用它的 message 中,而且,还可以将可被复用的字段在单独的一个文件中定义 message,然后使用关键字 import 导入该文件。
示例代码:
代码语言:javascript复制// 导入
import "enum.proto";
message User {
int64 id = 1;
string name = 2;
Gender gender = 4;
}
08
protoc 编译器
我们需要安装 protoc 编译器,编译我们编写的 proto 文件,生成指定编程语言的代码。
protoc 命令选项:
代码语言:javascript复制# 指定 proto 文件的目录
-IPATH, --proto_path=PATH
# 指定 go 文件输出目录
--go_out=dir_name
使用 protoc 编译 proto 文件,生成 golang 代码,需要安装一个包,go get -u github.com/golang/protobuf/protoc-gen-go
。
示例代码:
代码语言:javascript复制protoc --proto_path dir_name/ --go_out=dir_name/ dir_name/xx.proto
09
总结
本文我们介绍 gRPC 使用的接口设计语言 protobuf,需要注意的是 proto 文件中字段的编号必须保证唯一,使用 protoc 编译器编译 proto 文件生成指定编程语言的代码,protoc 原生不支持生成 golang 代码,需要安装一个包。
protoc 编译 proto 文件生成的指定编程语言的代码不可以直接修改,如果需要修改,可以修改 proto 文件,然后使用 protoc 重新编译。
限于篇幅,本文无法介绍 protobuf 的全部内容,关于 protobuf 的更多内容,比如枚举,map 等,建议感兴趣的读者朋友们阅读官方文档。