grpc之protobuf协议的一些实现
Protobuf#
Protocol Buffers是一种轻便高效的结构化数据存储格式,可用于结构化数据串行化,即序列化。适合于做数据存储或RPC数据交换格式。
优点:
- 序列化过程快,所需存储的字节数更少。紧凑的数据存储,快速解析
- 向后兼容性好。跨语言兼容性好
缺点:
- 自解释性不好,因为存储是按二进制来的,不适合来描述数据结构。
为什么要快于XML、JSON等存储格式
因为XML的封解包的过程,需要从文件中读出字符串,再转换为XML文档对象结构模型,之后再从XML文档对象结构模型中读取指定节点的字符串,最后再将这个字符串换成指定类型的变量。这个过程很复杂,需要耗费大量CPU计算来完成词法文法分析。
而Protobuf只需要将一个二进制序列,按照指定格式读取到对应类型即可。
varint编码原理#
编码
对于一个int32的数n,它会重复进行这样一个过程:
- 先判断前25位是不是全为0.
- 如果是则说明这个数已经要编码完了,直接转为一个字节,退出过程。
- 如果不是则说明还要继续编码,取n的后7位,给第8位添1后转为一个字节,然后将n右移7位,继续过程。
解码
- 初始化一个数n,令n等于0;
- 对于要解码的字节数组进行逆序,因为protobuf是小端存储的。
- 然后进行二进制转十进制求和算法,得到最后的数。
优点:
编码原理是基于一个事实,即在一般使用中,绝大部分用到的数都比较小,不至于用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。
作者:墨鱼-yyyl
出处:https://www.cnblogs.com/moyu-yyyl/p/18009684
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!