Protobuf(Protocol Buffer)是谷歌开源的性能优异、跨语言、跨平台的序列化库。
一, 发展过程:
proto1:2001年,Protobuf首先在Google内部创建,把它称之为 proto1,一直以来在Google的内部使用,其中也不断的演化。
proto2:Protobuf的开发者重写了Protobuf的实现,保留了proto1的大部分设计。开源的proto2不依赖任何的Google的库,代码也相当的清晰。2008年7月7日,Protobuf被公布出来。Protobuf得到了大家的广泛的关注, 逐步地得到了大家的认可,很多项目采用Protobuf进行消息的通讯,还有基于Protobuf的微服务框架GRPC。
proto3:2016年推出了Proto3。 Proto3简化了proto2的开发,提高了开发的效能,但是也带来了版本不兼容的问题。目前Protobuf的稳定版本是3.9.2,于2019年9月23日发布。
二, 序列化和反序列化:
序列化(serialization、marshalling)的过程是指将数据结构或者对象的状态转换成可以存储(比如文件、内存)或者传输的格式(比如网络)。
反序列化(deserialization、unmarshalling)就是反向操作的过程。
XML是一种基于文本的编码方式,易于阅读和理解,但是失去了紧凑的基于字节流的编码的优势。
JSON是一种更轻量级的基于文本的编码方式,经常用在client/server端的通讯中。
YAML类似JSON,新的特性更强大,更适合人类阅读,也更紧凑。
其他的序列化格式,如Thrift、Avro、BSON、CBOR、MessagePack等等。
Protobuf支持很多语言,比如C++、C#、Dart、Go、Java、Python、Rust等,同时也是跨平台的。
三,proto3使用demo:
创建一个demo_example.proto 其内部代码如下:
syntax = "proto3";
package vddp_proto.property_service;
message SetReq {
string str_signal_name = 1;
uint32 g_signal_value = 2;
float f_signal_value = 3;
}
【syntax = "proto3"; 】指定protobuf的版本,这里是以proto3格式定义。如果没有指定,默认以proto2格式定义。
【package vddp_proto.property_service; 】 定义proto的包名,包名可以避免对message 类型之间的名字冲突,同名的Message可以通过package进行区分。
【message SetReq {
string str_signal_name = 1;
uint32 g_signal_value = 2;
float f_signal_value = 3;
} 】 定义了一个message类型: SetReq , 它包含三个字段str_signal_name 、g_signal_value 、f_signal_value ,它会被protoc编译成不同的编程语言的相应对象。
字段是以[ "repeated" ] type fieldName "=" fieldNumber [ "[" fieldOptions "]" ] ";"格式定义的。
这个demo是一个简单的例子,采用了type fieldName "=" fieldNumber格式定义的。【注:后面要去学习 复杂的字段定义】
编译proto:在当前的目录下执行【protoc -I=. -I/user/local/include -I=$(GOPATH)/src --go_out=. demo_example.proto】, 可以将这个proto编译成Go的代码,因为这里我们使用了go_out输出格式。
【-I】指定protoc的搜索import的proto的文件夹。【demo中-I=. -I/user/local/include -I=$(GOPATH)/src搜索了三个路径】
【--go_out=. 】使用go_out输出格式,将proto编译成Go的代码,生成的代码指定放在本地文件夹【.】中。另外cpp_out用来生成C++代码,java_out产生Java代码,python_out产生python代码,类似地还有csharp_out、objc_out、ruby_out、php_out等参数。
四,proto更多的文本定义:
定义proto的版本:【syntax = "proto3";】
引入其它proto文件:【import "other.proto";】
定义proto的包名:【package signal.bar;】
定义option:【option java_package = "com.example.foo";】
option可以用在proto的scope中,或者message、enum、service的定义中。
可以是Protobuf定义的option,或者自定义的option。
option的定义格式是【"option" optionName "=" constant ";"】
五,proto中字段可以使用的数据类型:
- 数字类型: double、float、int32、int64、uint32、uint64、sint32、sint64: 存储长度可变的浮点数、整数、无符号整数和有符号整数
- 存储固定大小的数字类型:fixed32、fixed64、sfixed32、sfixed64: 存储空间固定
- 布尔类型: bool
- 字符串: string
- bytes: 字节数组
- messageType: 消息类型
- enumType:枚举类型
proto中数据类型与其他语言的对应关系:
| .proto Type | Notes | C++ Type | Java Type | Python Type[2] | Go Type | Ruby Type | C# Type | PHP Type | Dart Type |
|---|---|---|---|---|---|---|---|---|---|
| double | double | double | float | float64 | Float | double | float | double | |
| float | float | float | float | float32 | Float | float | float | double | |
| int32 | 使用可变长度编码。 | int32 | int | int | int32 | Fixnum or Bignum (as required) | int | integer | int |
| int64 | 使用可变长度编码。 | int64 | long | int/long[3] | int64 | Bignum | long | integer/string[5] | Int64 |
| uint32 | 使用可变长度编码。 | uint32 | int[1] | int/long[3] | uint32 | Fixnum or Bignum (as required) | uint | integer | int |
| uint64 | 使用可变长度编码。 | uint64 | long[1] | int/long[3] | uint64 | Bignum | ulong | integer/string[5] | Int64 |
| sint32 | 使用可变长度编码。 | int32 | int | int | int32 | Fixnum or Bignum (as required) | int | integer | int |
| sint64 | 使用可变长度编码。 | int64 | long | int/long[3] | int64 | Bignum | long | integer/string[5] | Int64 |
| fixed32 | 始终为四个字节。 | uint32 | int[1] | int/long[3] | uint32 | Fixnum or Bignum (as required) | uint | integer | int |
| fixed64 | 始终为八个字节。 | uint64 | long[1] | int/long[3] | uint64 | Bignum | ulong | integer/string[5] | Int64 |
| sfixed32 | 始终为四个字节。 | int32 | int | int | int32 | Fixnum or Bignum (as required) | int | integer | int |
| sfixed64 | 始终为八个字节。 | int64 | long | int/long[3] | int64 | Bignum | long | integer/string[5] | Int64 |
| bool | bool | boolean | bool | bool | TrueClass/FalseClass | bool | boolean | bool | |
| string | 字符串必须始终包含UTF-8编码或7位ASCII文本,并且不能超过232。 | string | String | str/unicode[4] | string | String (UTF-8) | string | string | String |
| bytes |
May contain any arbitrary sequence of bytes no longer than 232. 可以包含不超过232个任意字节序列。 | string | ByteString | str | []byte | String (ASCII-8BIT) | ByteString | string | List |

本文详细介绍了谷歌的Protocol Buffer(Protobuf),从其发展历程proto1、proto2到proto3,重点讲解了序列化和反序列化概念。Proto3简化了开发并支持多种语言和平台。通过一个Go语言的proto3使用示例,展示了如何定义消息类型并进行编译。此外,还列举了protobuf中可用的数据类型及其在不同语言中的映射。
292

被折叠的 条评论
为什么被折叠?



