背景
这里介绍一款十分有价值的序列化协议,dubbo也是很早就支持到了,就是大名鼎鼎的 "protobuf"。
协议内容
protobuf 协议需要有.proto 文件和 转换工具支持(https://github.com/protocolbuffers/protobuf/releases),我们这里为了简单采用 protostuff 进行测试,他们两者生成的二进制数据结构格式完全相同的,可以说protostuff 是一个基于Protobuf 的序列化工具,protostuff通过schema的形式简化了复杂的自定义过程。
protobuf 采用 T-L-V (Tag-Length-Value)作为存储方式,既压缩后的字节流为如下形式:

tag的计算公式为:变量索引 << 3 | wire_type
wire_type
那么分析下Tag,tag代表数据类型wire_type和变量索引index,基础数据类型总共有如下几种:

对应的java中Integer 则为 int32 编码方式为 Varint ,wireType = 0。
对应的java中Long 则为 int64 编码方式为 Varint ,wireType = 0。
对应的java中String 则为 string 编码方式为 length-delimi ,wireType = 2。
对应的java中Double 则为 double 编码方式为 64-bit ,wireType = 1。
变量索引
这个索引就是指我们类变量的顺序规则(仔细分析下,通过索引来定义属性位置,这样我们就不需像json一样每次都需要传递key参数,而只需要传递必须的value,但是这样带来一个明显的问题就是顺序和类型依赖很强)。
length&value
length 和 value 指的是后面变长内容的长度和序列化之后的字节内容。
编码规则
protobuf 有一套高效的编码方式,这里解释其中编码方式varint 和 zigzag 和 定长编码:
varint:将二进制从右到左边7位一次计算,直到读取最后有效位置,7位有效位如果非最后7位则前面补1进行编码
zigzag(如果为负数的情况): (n << 1) ^ (n >> 31)
定长编码:像字符串"abc",这种压缩则直接为ascii编码
思考:为什么负数和正数会不一样?
案例分析
协议是固定的,先不去质疑,我们运行如下案例,看看能否反推下,加深对协议的理解。java 要支持 protostuff 需要引入如下pom:
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>io.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.7.2</version>
</dependency>
定义一个需要序列化的对象
public class WishRequest implements Serializable {
private Integer age;
private Long money;
private String msg;
用protostuff 工具类进行压缩
public class ProtostuffTest {
public static void main(String[] arg

本文深入解析Protobuf协议的原理及其实现,通过具体案例详细介绍了其Tag-Length-Value的存储方式,同时展示了如何使用Protostuff工具进行序列化操作。此外,还分析了在Dubbo框架中Protobuf的应用细节。
最低0.47元/天 解锁文章
562

被折叠的 条评论
为什么被折叠?



