本文主要是介绍Proto3序列化协议,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
Proto3序列化协议
简介
对于互联网应用来说,客户端-客户端、客户端-服务端之间需要数据的交互,其数据传输是二进制流的方式在互联网上传输,因为需要一种手段将数据对象编码为一种可以在网络上传输的二进制流,这个过程就叫做序列化。同样的,客户端在收到二进制流需要解码出数据,这个过程叫反序列。
简单理解就是序列化就是按照某种编码方式将数据转换为二进制流以方便在网络上传输,同时这种编码方式是可逆的和可理解的。
按照上述定义不难理解,json
也是一种序列化的一种方式,将对象编码为字符串(二进制)进行传输。
同样的proto3是google推出的一种序列化框架。全称是Protocol Buffers。
其具有以下特点:
-
小:生成的字节流采用了各种压缩方式,相对xml和json这类文件更小。
-
快:编解码基本都是位运算,也没有复杂的嵌套关系,速度快。
-
安全:这里的安全,是指protobuf没有把字段名写入到字节流里,只是写入了字段号信息。另外,相对于xml和json来说,因为被编码成二进制,破解成本增大。
编码方式
我们定义了一个Person的消息类型,那protobuf是怎么把它编码成二进制的呢?其实它是把message转成一系列的key-value,key就是字段号,value就是字段值,大概这样子存:
message Person {string name = 1;int32 id = 2;
}
=1
,=2
称为tag
, 唯一标识每个元素,其值不可重复,其中tag在1-15之间编码为一个字节,大于15字节将需要多个字节进行编码,因此作为优化手段,1-15 tag多用户经常出现的元素,15+的tag用于不长出现或者可选的元素,此外,对于repeated类型的message,其每个元素都需要一个tag,所以repeated适合用小于15的tag。
对于上述的定义,其会按照[tag1][value1][tag2][value2][tag3][value3]...
的方式进行编码,
解码时,会从左往右解析每一个key-value,假如遇到某个key-value无法解析了,那么就直接跳过,不会影响到其它key-value的解析,因此如果你加了新字段,生成字节流,然后用旧版本解析,这时它还是能够解析出旧版本的字段的,新字段只是被忽略而已,这就是protobuf的向后兼容。
需要注意,一旦发布proto协议,其tag值就不能修改,新增字段只能使用未使用的tag(即使删除的tag也不可以),删除一个字段可以,解码时如果没有该字段会默认填充默认值,如果删除删除一个字段,最好采用reversed标识使用过的tag值,避免后续误使用旧的tag值。
官方建议:
-
xxx.proto
一行最多80字符 -
2个空格缩进
-
字符串用双引号
-
文件名
小写、_
组成,如lower_snake_case.proto
-
message 定义要驼峰式且首字母大写
message SongServiceRequest {required string song_name = 1;
}
-
如果成员变量包含数组,应采用
song_name1
而不是song_name_1
-
对于repeated类型应该用复数,如
repeated string keys = 1;
//类型是大写+驼峰式
enum FooBar {FOO_BAR_UNSPECIFIED = 0; // 0值定义UNSPECIFIEDFOO_BAR_FIRST_VALUE = 1; //值是全大写常量定义FOO_BAR_SECOND_VALUE = 2;
}
- 对于Services定义
//驼峰+大写service FooService {rpc GetSomething(FooRequest) returns (FooResponse); //函数名以驼峰+首字母大写}
这篇关于Proto3序列化协议的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!