Protobuf 原理及优点

Protocol Buffers (Protobuf) 是一种谷歌开发的二进制通信格式,用于序列化结构数据,截至目前,谷歌使用 protobuf 已经超过十年了。
Protobuf 的出现并不是为了解决新的问题,而是用更加现代的方式让网络传输更加高效,总的来说它有如下几个特点:

  1. 是二进制格式,而不是像 JSON 与 XML 是基于文本的,因此非常节省空间。
  2. 对各种模式丰富且易上手的支持。
  3. 支持多种语言下的解析。

那么,为何 protobuf 更加高效呢?下面来深入探索下这个问题。

protobuf 的编码方式

下面是一段要通过 protobuf 序列化传输数据的 .proto 文件。

message my_int_massage{
    int 32 a = 2009;
}

我们看到消息体中仅有一个32位的整数,那么protobuf 如何为它进行编码呢,能小于 32 位吗?下面介绍 varint,可变长整数编码,即 protobuf 所采用的,那么 varint 是如何工作的呢?
我们以上面的消息体定义作为例子:

  1. 将2009 转换为二进制 11111011001
  2. 将其分割为 0001111 1011001
  3. 反转其顺序 1011001 0001111
  4. 添加 MSB 标识为 01011001 00001111
  5. 设置MSB ,11011001 00001111 (即第一位为0代表是数字结尾)
  6. 最后用16进制表示为 D9 0F
    以上就是protobuf 编码的过程,那么如何编码多个数字呢,下面介绍一下序列数,它由 field_num, write_type 决定,即(filed_number<< 3) | write_type ,其本身也是被 varint 编码,后 3 由 write_type 决定。其中 field_number 表示当前是第几位数字,write_type 表示该数字的编码方式是 varint ,varint 时 write_type 为0;

那么如何解码呢,与编码对应,先根据 MSB 位取数据,然后去掉 MSB 位,反转数据,解码即可。

那么 string 呢?

对于 utf-8 或7-bit ASCII 编码的 stirng,首先,同样有field_number 与 write_type 组成的 序列数, string 的序列数为2,此外在序列数之后还有表示 string 长度的字段,由于已经有长度信息,因此string 的编码不再需要 MSB 标识位。
例如:“syma” 编码为 0A 04 73 79 6d 61;(0A是序列数,04是长度,其他为字符串);

小结

1.在微服务之间通信时,protobuf 更合适,在公开 API 或与浏览器通信时JSON 与 xml 更合适。

  1. protobuf 更加节省空间,高效。
  2. protobuf 放弃了可读性。
  3. protobuf 使用的编码方式可以使数据更加紧凑。
    5.protobuf 依赖生成的代码,需要一个protobuf 编译器根据你编写的 .proto 定义的数据生成,也称作消息。
  4. 你可以根据生成的代码初始化或解析发生的数据或接受的数据。

你可能感兴趣的:(Protobuf 原理及优点)