grpc之protobuf协议的一些实现

Protobuf

Protocol Buffers是一种轻便高效的结构化数据存储格式,可用于结构化数据串行化,即序列化。适合于做数据存储或RPC数据交换格式。

优点:

  1. 序列化过程快,所需存储的字节数更少。紧凑的数据存储,快速解析
  2. 向后兼容性好。跨语言兼容性好

缺点:

  1. 自解释性不好,因为存储是按二进制来的,不适合来描述数据结构。

为什么要快于XML、JSON等存储格式

因为XML的封解包的过程,需要从文件中读出字符串,再转换为XML文档对象结构模型,之后再从XML文档对象结构模型中读取指定节点的字符串,最后再将这个字符串换成指定类型的变量。这个过程很复杂,需要耗费大量CPU计算来完成词法文法分析。

而Protobuf只需要将一个二进制序列,按照指定格式读取到对应类型即可。

varint编码原理

编码

对于一个int32的数n,它会重复进行这样一个过程:

  1. 先判断前25位是不是全为0.
  2. 如果是则说明这个数已经要编码完了,直接转为一个字节,退出过程。
  3. 如果不是则说明还要继续编码,取n的后7位,给第8位添1后转为一个字节,然后将n右移7位,继续过程。
解码
  1. 初始化一个数n,令n等于0;
  2. 对于要解码的字节数组进行逆序,因为protobuf是小端存储的。
  3. 然后进行二进制转十进制求和算法,得到最后的数。

优点:

编码原理是基于一个事实,即在一般使用中,绝大部分用到的数都比较小,不至于用32位来存储,会形成很大浪费。因此对于这个数的高位0进行省略。虽然对于那些很大的数会用40位去存储,但在实际应用中,消耗的内存还是大大减少了。

缺点:

由于负数的存储是用的补码,高位是1,会导致varint编码特别大,必定消耗5个字节。因此需要用zigzag来辅助对负数进行编码。

zigzag编码原理

编码

对于负数n,返回 (n<<1)^(n>>31),然后将返回的数按varint进行编码

实质是将负数的符号位移到了最后一位。

解码

对于字节数组,先按照varint进行解码,获得数n,返回 (n>>>1)^-(n&1)

存储格式T-L-V

Tag

Tag=(field_number<<3)|wire_type

field_number表示消息中的第几个字段,不允许重复,推荐0~15,会节省字节。

wire_type是0~5,需要3个bit位存储,用于表示不同的数据类型。

Length

对于不同的数据类型,会决定它是否需要Length这个字段。

  • Tag:用varint进行编码
  • Length:用varint编码
  • Value:1.string类型用utf8编码。2.Message是根据内部类型来编码

repeated类型

repeated类型可看作数组,存储形式是T-L-V。每一个元素都会附加一个相同的Tag,因此有冗余浪费。在末尾加上packed=true字段可以进行压缩,只使用一个Tag。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值