cfanbo / cfanbo.github.io

1 stars 0 forks source link

Protobuf协议实现原理 | 学习笔记 #213

Open cfanbo opened 1 year ago

cfanbo commented 1 year ago

https://blog.haohtml.com/archives/20215

protobuf是Google开源的一款支持跨平台、语言中立的结构化数据描述和高性能序列化协议,此协议完全基于二进制,所以性能要远远高于JSON/XML。由于出色的传输性能因此常见于微服务之间的通讯,其中最为著名的是Google开源的 gRPC 框架。 那么protobuf是如何实现高性能的,又是如何实现数据的编码和解码的呢? protobuf协议原理 基于128bits的数据存储方式(Base 128 Varints) Varint 是一种紧凑的表示数字的方法。它用一个或多个字节来表示一个数字,值越小的数字使用越少的字节数。这能减少用来表示数字的字节数。 比如对于 int32 类型的数字,一般需要 4 个 byte 来表示。但是采用 Varint,对于很小的 int32 类型的数字,则可以用 1 个 byte 来表示。当然凡事都有好的也有不好的一面,采用 Varint 表示法,大的数字则需要 5 个 byte 来表示。从统计的角度来说,一般不会所有的消息中的数字都是大数,因此大多数情况下,采用 Varint 后,可以用更少的字节数来表示数字信息 Varint 中的每个 byte 的最高位 bit 有特殊的含义,如果该位为 1,表示后续的 byte 也是该数字的一部分;如果该位为 0,则结束。其他的 7 个 bit 都用来表示数字。因此小于 128 的数字都可以用一个 byte 表示。大于 128 的数字,比如 300,会用两个字节来表示: 1010 1100 0000 0010。 另外如果从数据大小角度来看,这种表示方式比真正要代表的数据多了一个bit, 所以其实际传输大小就多14%(1/7 = 0.142857143),对于这一点我们需要有所了解。 下面我们看一个例子: 数字1表示方式:0000 0001 对于小的数据比较好理解,正常情况下1的二进制是 0000 0001,使用128bits表示的话,首位结束标识位也是0,所以两者结果是一样的 000 0001。 上面是对小数据(<=128)的表示方法,我们再看一下非小数据(>128)的表示方法