介绍
在学习 gRPC 之前,我们需要先了解 Protocal Buffers,也就是 protobuf,它是接口设计语言(IDL),它与编程语言无关,可以生成所有主流编程语言的代码,而且,它是二进制格式的数据,比较适合传递大量的数据。
在编写 gRPC 代码之前,首先使用 protobuf 定义服务端和客户端之间传递的消息(message)和 gRPC 服务(service),然后安装需要用到的库,使用命令行工具自动生成 gRPC 的代码。
protobuf 语法
protobuf 文件是以 .proto
后缀名结尾,一般会在文件开头声明 proto 的版本,syntax = "proto3";
,如果不声明,则默认使用 proto2 版本。
接下来,我们就可以开始定义消息(message),使用关键字 message
,message User {}
,然后在大括号中定义字段。
示例代码:
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 中是该字段类型的切片。
示例代码:
message User { int64 id = 1; string name = 2; repeated string emails = 3; }
05
protobuf 字段变更
在应用程序开发中,可能会遇到字段修改或删除,protobuf 不允许修改字段的编号(tag),但是可以删除字段,前提是被删除的字段的编号不再被其他字段使用,一般有两种方式,一种是在需要删除的字段名前添加前缀 OBSOLETE_
,而不是删除该字段;另一种方式是把需要删除的字段的编号(tag)使用关键字 reserved
保留,避免被其他字段使用被删除字段的编号(tag)。
关键字 reserved
除了可以保留字段编号之外,还可以保留字段名称,可用于设置禁用字段名。
示例代码:
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),我们可以使用包名做区分。
示例代码:
// 定义包名 package user; // 定义 golang 包名 option go_package = "userpb";
07
protobuf 嵌套和导入
如果定义的 message 包含一些可以复用的字段,我们可以使用嵌套的方式,将可被复用的字段单独定义为 message,然后嵌套在需要使用它的 message 中,而且,还可以将可被复用的字段在单独的一个文件中定义 message,然后使用关键字 import 导入该文件。
示例代码:
// 导入 import "enum.proto"; message User { int64 id = 1; string name = 2; Gender gender = 4; }
08
protoc 编译器
我们需要安装 protoc 编译器,编译我们编写的 proto 文件,生成指定编程语言的代码。
protoc 命令选项:
# 指定 proto 文件的目录 -IPATH, --proto_path=PATH # 指定 go 文件输出目录 --go_out=dir_name
使用 protoc 编译 proto 文件,生成 golang 代码,需要安装一个包,go get -u github.com/golang/protobuf/protoc-gen-go
。
示例代码:
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 等,建议感兴趣的读者朋友们阅读官方文档。
推荐阅读:
参考资料:
https://developers.google.com/protocol-buffers/docs/proto3