Protocol Buffers 数据解析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Protocol Buffers 数据解析相关的知识,希望对你有一定的参考价值。

参考技术A 突然间,好像对ProtoBuf有点陌生的感觉,特此复习一下。

Protocol Buffers可以理解为更快、更简单、更小的JSON或者XML,区别在于Protocol Buffers是二进制格式,而JSON和XML是文本格式。

Protobuf经序列化后以二进制数据流形式存储,这个数据流是一系列key-Value对。Key用来标识具体的Field,在解包的时候,Protobuf根据 Key 就可以知道相应的 Value 应该对应于消息中的哪一个 Field。

Key 的定义如下:

Key由两部分组成。第一部分是 field_number,比如消息 tutorial .Person中 field name 的 field_number 为 1。第二部分为 wire_type。表示 Value 的传输类型。Wire Type 可能的类型如下表所示:

Protobuf的二进制使用Varint编码。Varint 是一种紧凑的表示数字的方法。它用一个或多个字节来表示一个数字,值越小的数字使用越少的字节数。这能减少用来表示数字的字节数。

Varint 中的每个 byte 的最高位 bit 有特殊的含义,如果该位为 1,表示后续的 byte 也是该数字的一部分,如果该位为 0,则结束。其他的 7 个 bit 都用来表示数字。因此小于 128 的数字都可以用一个 byte 表示。大于 128 的数字,比如下面demo中的2000 就是用两个字节来表示。

Demo Code 主要对比了一下,用Gzip 压缩序列化的Json数据与Protobuf 数据的速度和大小对比。可以看到,Protobuf 最大的一个优点果然是在数据压缩方面。那么数据是如何存取的呢?

下面是一段Json数据:

它对应的的pb 数据为:
<0a057665 646f6e10 1b1a0b31 35303138 34393233 35782215 e5b9bfe5 b79ee5b8 82e5b9b3 e4ba91e5 b9bfe59c ba2802>

Key :
0a = 0000 1010
=> 0001 010
=> field_num = 0001 ,type = 010
=> field_num = 1,type = 2

Value:
05 = 0000 0101
=> 000 0101 (去掉最高位)
=> 5

读取5个字符:
userName = 76 65 64 6f 6e => v e d o n

Key :
10 = 0001 0000
=> 001 0000 (去掉最高位)
=> field_num = 0010 ,type = 000
=> field_num = 2 ,type = 0

Value
1b = 0001 1011
=> 27
age = 27 .

Key:
1a = 0001 1010
=> 001 1010 (去掉最高位)
=> field_num = 0011 ,type = 010
=> field_num = 3 ,type = 2

Value:
0b = 0000 1011
=> 11

读取11个字符:
31 35 30 31 38 34 39 32 33 35 78 => 1 5 0 1 8 4 9 2 3 5 x

Protobuf 相比 JSON 的优势在于它本身带有严格的 schema validation,一份 .proto 文件既作为 input/output 的入口,又作为规定数据格式的文档。例如:后端给一份.proto 文件,通过官方提供的工具,生成对应的oc 类,在跨语言多人协作的项目上用起来不能更爽。

Protobuf 是 schema + data format,schema 是我们可以看见的 proto 文件里的定义,data format 是它序列化成二进制数据的格式。

最终选择的时候还有个很关键的因素,就是公司整个大环境的技术选型,如果你所依赖的其他组件用 JSON 的较多,那么也不要刻意用 Protobuf 。如果一个大型项目在一开始就用了 Protobuf 作为数据格式的约定,后期在数据一致性上可能出现很多麻烦就可以避免掉呢。

详细的性能分析,网上已经有很详细的了。这里推荐一篇文章: Beating JSON performance with Protobuf

如何在 PHP 中处理 Protocol Buffers 数据

Protocol Buffers是谷歌定义的一种跨语言、跨平台、可扩展的数据传输及存储的协议,因为将字段协议分别放在传输两端,传输数据中只包含数据本身,不需要包含字段说明,所以传输数据量小,解析效率高。感兴趣的可以访问这里。Protocol Buffers官方只支持C++, Java, Python, C#, Go,如果想在PHP中使用Protocol Buffers,需要借助于第三方的扩展,使用方法如下。

安装protoc编译器

第一步,安装Google的protoc编译器,这个工具可以把proto文件中定义的Message转换为各种编程语言中的类。下载release版本直接编译安装。

下载地址

安装PHP Plugin

第二步,安装protoc的PHP plugin,需要使用composer安装,感兴趣的可以访问http://www.phpcomposer.com

这个插件可以将proto文件转换到PHP文件,在PHP应用中引用后,可以将二进制格式的Protocol Buffers数据转换为PHP的对象

下载地址

安装php-protocolbuffers

第三步,安装php-protocolbuffers,这是一个PHP扩展,在第二步中已经完成了proto文件到PHP文件的转换,但是对PHP对象的各种操作还需要这个扩展中的API方法

然后在你的php.ini配置文件中添加

编写代码

第四步,借助上面提到的扩展的各种API方法,可以简单地get出自己需要的字段完成后续工作

以上是关于Protocol Buffers 数据解析的主要内容,如果未能解决你的问题,请参考以下文章

Java使用Protocol Buffers入门四步骤

为 Google Protocol Buffer 解析文本文件

protocol buffers的编码原理

如何在 Protocol Buffers 中构建数据模型

Protocol Buffers 介绍

Google Protocol Buffers 入门