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值定义UNSPECIFIED
  FOO_BAR_FIRST_VALUE = 1;  //值是全大写常量定义
  FOO_BAR_SECOND_VALUE = 2;
}

  • 对于Services定义
  //驼峰+大写
  service FooService {
      rpc GetSomething(FooRequest) returns (FooResponse); //函数名以驼峰+首字母大写
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值