现在的位置: 首页 > 综合 > 正文

关于Google protobuf的总结

2013年05月11日 ⁄ 综合 ⁄ 共 2480字 ⁄ 字号 评论关闭

在现在的技术体系中,能用于描述通信协议的方式很多,如xml/json/protobuf/thrift等。一条消息数据,用protobuf序列化后的大小是json格式的十分之一,xml格式的二十分之一,是二进制序列化的十分之一。至于thrift,它文档匮乏。这样,使得protobuf在性能和文档完备上高出一个档次。

protobuf是google提供的一个开源序列化框架,它在google中是一个比较核心的基础库,作为分布式运算涉及到大量的不同业务消息的传递,如何高效简洁的表示、操作这些业务消息在google这样的大规模应用中是至关重要的。而protobuf这样的库正好是在效率、数据大小、易用性之间取得了很好的平衡。

protobuf类似于XML,JSON这样的数据表示语言,其最大的特点是基于二进制,因此比传统的XML表示高效短小得多。虽然是二进制数据格式,但并没有因此变得复杂,开发人员通过按照一定的语法定义结构化的消息格式,然后送给命令行工具,工具将自动生成相关的类,可以支持java、c++、python等语言环境。通过将这些类包含在项目中,可以很轻松的调用相关方法来完成业务消息的序列化与反序列化工作。

protobuf是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它的设计非常适用于在网络通讯中的数据载体,很适合做数据存储或 RPC 数据交换格式,它序列化出来的数据量少再加上以K-V的方式来存储数据,对消息的版本兼容性非常强,可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。

使用protobuf时,你可以定义自己的数据结构,然后使用代码生成器生成的代码来读写这个数据结构。你甚至可以在无需重新部署程序的情况下更新数据结构。只需使用 Protobuf 对数据结构进行一次描述,即可利用各种不同语言或从各种不同数据流中对你的结构化数据轻松读写。它有一个非常棒的特性,即“向后”兼容性好,人们不必破坏已部署的、依靠“老”数据格式的程序就可以对数据结构进行升级。这样你的程序就可以不必担心因为消息结构的改变而造成的大规模的代码重构或者迁移的问题。因为添加新的消息中的 field 并不会引起已经发布的程序的任何改变。

人们一直在强调,同XML相比,protobuf的主要优点在于性能高。从Protobuf 序列化后的信息内容,可以看到 Protocol Buffer 信息的表示非常紧凑,这意味着消息的体积减少,自然需要更少的资源。比如网络上传输的字节数更少,需要的 IO 更少等,从而提高性能。它以高效的二进制方式存储,比XML小3到10倍,快20到100倍。对于这个“3到10倍,快20到100倍”的说法,protobuf的两项技术给予了证明。

第一点,Protobuf 序列化后所生成的二进制消息非常紧凑,得益于 Protobuf 采用的非常巧妙的 Encoding 方法:Zigzag 编码。

介绍Zigzag编码前,先普及一下一个叫做 Varint 的术语。

Varint 是一种紧凑的表示数字的方法。它用一个或多个字节来表示一个数字,值越小的数字使用越少的字节数。这能减少用来表示数字的字节数。比如对于 int32 类型的数字,一般需要 4 个 byte 来表示。但是采用 Varint,对于很小的 int32 类型的数字,则可以用 1 个 byte 来表示。当然凡事都有好的也有不好的一面,采用 Varint 表示法,大的数字则需要 5 个 byte 来表示。从统计的角度来说,一般不会所有的消息中的数字都是大数,因此大多数情况下,采用 Varint 后,可以用更少的字节数来表示数字信息。下面就详细介绍一下
Varint。

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

在计算机内,一个负数一般会被表示为一个很大的整数,因为计算机定义负数的符号位为数字的最高位。如果采用 Varint 表示一个负数,那么一定需要 5 个 byte。为此 Google Protocol Buffer 定义了 sint32 这种类型,采用 zigzag 编码,用无符号数来表示有符号数字,正数和负数交错,-1将会被编码成1,1将会被编码成2,-2会被编码成3。

第二点,Protobuf 封解包的过程。

先来了解一下 XML 的封解包过程。XML 需要从文件中读取出字符串,再转换为 XML 文档对象结构模型。之后,再从 XML 文档对象结构模型中读取指定节点的字符串,最后再将这个字符串转换成指定类型的变量。这个过程非常复杂,其中将 XML 文件转换为文档对象结构模型的过程通常需要完成词法文法分析等大量消耗 CPU 的复杂计算。

反观 Protobuf,它只需要简单地将一个二进制序列,按照指定的格式读取到对应的结构类型中就可以了,速度非常快。

饮水思源:

https://developers.google.com/protocol-buffers/docs/overview?hl=zh-CN&csw=1

http://www.ibm.com/developerworks/cn/linux/l-cn-gpb/

http://www.myexception.cn/program/866943.html

http://maoyidao.iteye.com/blog/1236916

http://timyang.net/programming/thrift-protocol-buffers-performance-2/

http://chengxu.org/p/440.html

http://djt.qq.com/article/view/327

http://www.csdn.net/article/2012-11-16/2811949

http://agapple.iteye.com/blog/859052

抱歉!评论已关闭.