Protobuf 入门教程
在 Kafka 中,发送的消息是字节数组,因此就需要一个方法来将消息对象序列化为字节数组,在消费者端再反序列化为对象。最常用的序列化格式就是 JSON 了。虽然 JSON 对人类非常友好,但是对于机器来说,更容易进行序列化和反序列化的格式还是二进制的格式。
Protobuf(Protocol buffers)是由 Google 开发的一种二进制协议,用于对结构化数据进行序列化和反序列化。这种格式占用空间更少,更加简单易于维护,同时拥有更好的性能。对于机器之间的通信,Protobuf 是比 XML 和 JSON 等格式更好的一种选择。
Protobuf 的使用相比之下更加复杂,需要编写.proto 格式的文件来定义数据格式,之后通过 protoc 编译器将其编译到对应的语言,之后再在程序中引用。
使用
安装
首先就是安装 protoc 编译器,这个编译器可以直接到 github 上下载二进制包,解压到对应位置并设置 PATH 即可。
之后就是安装对应语言的客户端,对于 golang,执行下面两条语句安装就可以了:
go get github.com/golang/protobuf/proto go get github.com/golang/protobuf/protoc-gen-go
编译
之后新建一个.proto 文件,在其中定义消息的格式:
syntax = "proto3"; package test; option go_package = "proto/test"; message Award { int64 uid = 1; int64 awardId = 2; string userName = 3; }
然后使用 protoc 编译器将其编译到 go 文件就行了:
protoc --go_out=. proto/*.proto
在 go 程序中引入生成的包就可以进行序列化和反序列化了:
import pb "proto/test"
func marshal() {
award := &pb.Award{
Uid: 628,
AwardId: 1,
UserName: "Haruka",
}
msg, err := proto.Marshal(award)
}
func unmarshal() {
award := &pb.Award{}
if err := proto.Unmarshal(msg.Value, award); err != nil {
panic(err)
}
}
proto3 语言
在.proto 文件的第一行就是 syntax = "proto3";,用于声明该文件是 proto3 版本的。之后可以声明 package 用于避免命名冲突,最后就可以定义 message 了。
字段 ID
message 的每个字段都要分配一个唯一的 ID,最小是 1 最大是 2^29 - 1,同时不能使用 1900019999 的 ID。ID 可以任意分配,但是 115 只会占用 1 个字节,而 16~2047 会占用 2 个字节,因此应尽量从小开始分配,并将小的分配给最经常出现的字段。
可以使用 reserved 来对字段名和 ID 进行保留,一般用于为未来新增字段保留,或者保留删除字段来避免之后的字段使用,防止发生冲突:
message Foo { reserved 2, 15, 9 to 11; reserved "foo", "bar"; }
字段类型
字段的类型默认是 singular,也就是只能出现一次或 0 次,如果在字段声明前加上 repeated 的话就可以出现多次。
protobuf 的标量类型有以下几种:double float int32 int64 uint32 uint64 sint32 sint64 fixed32 fixed64 sfixed32 sfixed64 bool string bytes。
protobuf 中还可以使用枚举和复合类型。例如可以通过 import "google/protobuf/timestamp.proto"来使用 timestamp 类型。
protobuf 数据类型的默认值规则如下,如果一个字段被设置为默认值,则其不会被序列化:
- string bytes 类型默认为空
- bool 类型默认为 false
- 数值类型默认为 0
- 枚举类型默认为第一个,即 0
- 复合类型取决于语言
枚举类型
message SearchRequest {
enum Corpus {
option allow_alias = true;
UNIVERSAL = 0;
WEB = 1;
TEST = 1;
IMAGES = 2;
}
Corpus corpus = 4;
}
通过 enum 来声明一个枚举,注意枚举中必须要有 0 值用来作为默认值,同时 0 值应该是第一个元素,以与 proto2 兼容。通过 option allow_alias = true;来允许两个枚举元素有相同的值,即这两个元素可以相互替代。
复合类型
在一个 message 中,可以嵌入其他的 message 作为复合类型:
message SearchResponse { repeated Result results = 1; } message Result { string url = 1; string title = 2; repeated string snippets = 3; }
在 protobuf 中还有其他高级类型,如 Any oneof map 等,就不详细介绍了。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: Go 程序是怎样跑起来的
下一篇: MyBatis 介绍和使用
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论