【得物技术】dubbo系列之-序列化

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

背景

这里介绍一款十分有价值的序列化协议,dubbo也是很早就支持到了,就是大名鼎鼎的 "protobuf"。

协议内容

protobuf 协议需要有.proto 文件和 转换工具支持https://github.com/protocolbuffers/protobuf/releases),我们这里为了简单采用 protostuff 进行测试,他们两者生成的二进制数据结构格式完全相同的,可以说protostuff 是一个基于Protobuf 的序列化工具,protostuff通过schema的形式简化了复杂的自定义过程。

protobuf 采用 T-L-V (Tag-Length-Value)作为存储方式,既压缩后的字节流为如下形式:

image.png

tag的计算公式为:变量索引 << 3 | wire_type

wire_type

那么分析下Tag,tag代表数据类型wire_type和变量索引index,基础数据类型总共有如下几种:

image.png

对应的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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值