Protocol Buffers 序列化协议及应用

本贴最后更新于 1836 天前,其中的信息可能已经事过景迁

Protocol Buffers 是 Google 开发一种数据描述语言,能够将结构化数据序列化,可用于数据存储、通信协议等方面。据 Google 官方文档介绍,现在 Google 内部已经有 48,162 个消息类型定义在 12,183 个 proto 文件中。本文会从快速入门、语言规范、编码协议、性能评估等几个方面对 Prototol Buffers 进行介绍。

替代文字

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

替代文字

相对于 XML,Protocol Buffers 的具有如下几个优点:

  • 简洁
  • 体积小:消息大小只需要 XML 的 1/10 ~ 1/3
  • 速度快:解析速度比 XML 快 20 ~ 100 倍
  • 使用 Protocol Buffers 的编译器,可以生成更容易在编程中使用的数据访问代码
  • 更好的兼容性,Protocol Buffers 设计的一个原则就是要能够很好的支持向下或向上兼容。

替代文字

看一个简单的对比例子,表达一个用户的三个基本的属性,如果使用 XML 消息体大小为 82 bytes。

替代文字

如果使用 JSON 消息体大小为 56 bytes。

替代文字

使用 Protocol Buffers 咋则只需要 31 bytes,看到这些二进制数据大家可以暂时忽略,后面会具体分析这些二进制数据是如何编码的。

替代文字

接下来先看一个简单的入门示例,在该例子中我们从准备环境开始,编写 proto 文件,到最后使用 Protocol Buffers 编译器生成代码,再到具体的使用。

替代文字

https://github.com/google/protobuf 下载编译安装 protoc,并下载 ProtobufSDK。

替代文字

开始编写 proto 文件,使用 message 关键字定义消息类型,消息中每个字段需要指定字段类型和字段序号。同一个 message 中字段

替代文字

使用 protoc 命令生成代码,使用--cpp_out、--java_out、--python_out 命令选项可以生成 C++、Java、Python 代码,在最新版本 Protocol Buffers v3 中还加入了 ruby 语言的支持。

替代文字

生成代码的代码可以直接加入到自己的代码工程中使用,以 C++ 语言为例:

替代文字

这是一段 Java 语言的使用示例:

替代文字

接下来会详细说明如何定义 proto 文件:

替代文字

在消息定义中,我们需要确定三个问题:

  • 确定消息命名,给消息取一个有意义的名字。

  • 指定字段的类型

  • 定义字段的编号,在 Protocol Buffers 中,字段的编号非常重要,字段名仅仅是作为参考和生成代码用。需要注意的是字段的编号区间范围,其中 19000 ~ 19999 被 Protocol Buffers 作为保留字段。

    替代文字

    字段约束,required 指定该字段必须赋值,禁止为空(在 v3 中该约束被移除);optional 指定字段为可选字段,可以为空,对于 optional 字段还可以使用[default]指定默认值,如果没有指定,则会使用字段类型的默认值;使用 repeated 指定字段为集合。

    替代文字

    在一个 proto 文件中可以同时定义多个 message 类型,生成代码时根据生成代码的目标语言不同,处理的方式不太一样,如 Java 会针对每个 message 类型生成一个.java 文件。还可以使用 C++ 风格的注释。

    替代文字

    在 Protocol Buffers 中提供了很多的标量类型,供我们在定义字段类型时使用。

    替代文字

    可以指定字段的类型为其他 message 类型,如图中的示例代码所示:

    替代文字

    还可以使用 import 关键字导入其他 proto 文件,这有利于你进行自己的 proto 文件的规划和整理。

    替代文字

    在 proto 文件中消息的类型还可以嵌套,如你定义的 message 类型仅作为另外一个 Message 的字段类型。

    替代文字

    为了便于扩展,在 proto 文件中可以使用 extensions 关键字预留一部分字段编号出来,以便于后期给第三方扩展时使用。

    替代文字

    oneof 关键字指定一组字段中,至少要有一个字段必须赋值。如在用户登录系统中,使用邮箱和用户名都可以登录该系统,所以通常会要求至少提供用户名或者邮箱。

    替代文字

    在这一部分总我们会仔细分析,Protocol Buffers 序列化后的二进制代码的编码协议,不知道这些并不会影响我们使用 Protocol Buffers,但是了解之后有助于我们更好的使用 Protocol Buffers 和进行调试。

    替代文字

    先从一个简单的例子开始,如图中的代码所示,我们有这样一个消息定义,在使用中给 a 赋值为 150,最终编码得到的结果是 08 96 01,为什么编码的结果是这样,其中 08 又代表什么?后续一一为你介绍。

    替代文字

    在 Protocol Buffers 中采用 Base-128 变长编码,所谓变长编码是和定长编码相对的,定长编码使用固定字节数来表示,如 int32 类型的数字固定使用 4 bytes 表示,而变长编码是需要几个字节就使用几个字节,如对于 int32 类型的数字 1 来说,只需要 1 bytes 足够。Base-128 变长编码的原则就两条:

  • 每个字节使用使用低 7 位表示数字,除了最后一个字节,其他字节的最高位都设置为 1。

  • 采用 Little-Endian 字节序

替代文字

一个 Protocol Buffers 的消息包含一系列字段 key/value,每个字段由一个变长 32 位整数作为字段头,后面跟随字段体。字段头的格式如下:

(field_number << 3) | wire_type

-field_number:    字段序号 
-wire_type:    字段编码类型 

替代文字

这里是详细的字段说明,其中 3、4 已经放弃:

替代文字

替代文字

替代文字

替代文字

替代文字

替代文字

接下来我们对 Protocol Buffers 的性能做一些测试。

替代文字

在测试过程中,我们使用一个统一的消息体格式,主要评估以下两个性能指标:

  • 序列化速度
  • 报文大小

替代文字

替代文字

替代文字

替代文字

替代文字

尽管 Protocol Buffers 有序列化速度快、报文体积小以及更好的兼容性等优点,但同时也有一些缺点,在使用时要根据实际情况来选择使用。

  • 缺乏自描述,可读性差,可以使用 TextFormat
  • 适用于内部服务和存储,而不适合直接对外公开,如 Open API,protobuf v3 将加入对 json 的支持,可解决此问题

替代文字

与 Protocol Buffers 类似的框架有微软出的 Bond 和 Facebook 出的 Thrift,感兴趣的同学可以去下载研究一下。

替代文字

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Hprose

    Hprose 是一款先进的轻量级、跨语言、跨平台、无侵入式、高性能动态远程对象调用引擎库。它不仅简单易用,而且功能强大。你无需专门学习,只需看上几眼,就能用它轻松构建分布式应用系统。

    9 引用 • 17 回帖 • 597 关注
  • 七牛云

    七牛云是国内领先的企业级公有云服务商,致力于打造以数据为核心的场景化 PaaS 服务。围绕富媒体场景,七牛先后推出了对象存储,融合 CDN 加速,数据通用处理,内容反垃圾服务,以及直播云服务等。

    25 引用 • 217 回帖 • 162 关注
  • Pipe

    Pipe 是一款小而美的开源博客平台。Pipe 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    131 引用 • 1114 回帖 • 150 关注
  • 京东

    京东是中国最大的自营式电商企业,2015 年第一季度在中国自营式 B2C 电商市场的占有率为 56.3%。2014 年 5 月,京东在美国纳斯达克证券交易所正式挂牌上市(股票代码:JD),是中国第一个成功赴美上市的大型综合型电商平台,与腾讯、百度等中国互联网巨头共同跻身全球前十大互联网公司排行榜。

    14 引用 • 102 回帖 • 404 关注
  • 单点登录

    单点登录(Single Sign On)是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

    9 引用 • 25 回帖 • 3 关注
  • Google

    Google(Google Inc.,NASDAQ:GOOG)是一家美国上市公司(公有股份公司),于 1998 年 9 月 7 日以私有股份公司的形式创立,设计并管理一个互联网搜索引擎。Google 公司的总部称作“Googleplex”,它位于加利福尼亚山景城。Google 目前被公认为是全球规模最大的搜索引擎,它提供了简单易用的免费服务。不作恶(Don't be evil)是谷歌公司的一项非正式的公司口号。

    49 引用 • 192 回帖
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    198 引用 • 120 回帖
  • 人工智能

    人工智能(Artificial Intelligence)是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门技术科学。

    75 引用 • 146 回帖 • 1 关注
  • Solo

    Solo 是一款小而美的开源博客系统,专为程序员设计。Solo 有着非常活跃的社区,可将文章作为帖子推送到社区,来自社区的回帖将作为博客评论进行联动(具体细节请浏览 B3log 构思 - 分布式社区网络)。

    这是一种全新的网络社区体验,让热爱记录和分享的你不再感到孤单!

    1425 引用 • 10043 回帖 • 471 关注
  • OpenShift

    红帽提供的 PaaS 云,支持多种编程语言,为开发人员提供了更为灵活的框架、存储选择。

    14 引用 • 20 回帖 • 604 关注
  • BookxNote

    BookxNote 是一款全新的电子书学习工具,助力您的学习与思考,让您的大脑更高效的记忆。

    笔记整理交给我,一心只读圣贤书。

    1 引用 • 1 回帖
  • H2

    H2 是一个开源的嵌入式数据库引擎,采用 Java 语言编写,不受平台的限制,同时 H2 提供了一个十分方便的 web 控制台用于操作和管理数据库内容。H2 还提供兼容模式,可以兼容一些主流的数据库,因此采用 H2 作为开发期的数据库非常方便。

    11 引用 • 54 回帖 • 642 关注
  • 链书

    链书(Chainbook)是 B3log 开源社区提供的区块链纸质书交易平台,通过 B3T 实现共享激励与价值链。可将你的闲置书籍上架到链书,我们共同构建这个全新的交易平台,让闲置书籍继续发挥它的价值。

    链书社

    链书目前已经下线,也许以后还有计划重制上线。

    14 引用 • 257 回帖 • 4 关注
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    536 引用 • 672 回帖
  • 星云链

    星云链是一个开源公链,业内简单的将其称为区块链上的谷歌。其实它不仅仅是区块链搜索引擎,一个公链的所有功能,它基本都有,比如你可以用它来开发部署你的去中心化的 APP,你可以在上面编写智能合约,发送交易等等。3 分钟快速接入星云链 (NAS) 测试网

    3 引用 • 16 回帖
  • MyBatis

    MyBatis 本是 Apache 软件基金会 的一个开源项目 iBatis,2010 年这个项目由 Apache 软件基金会迁移到了 google code,并且改名为 MyBatis ,2013 年 11 月再次迁移到了 GitHub。

    170 引用 • 414 回帖 • 429 关注
  • Swift

    Swift 是苹果于 2014 年 WWDC(苹果开发者大会)发布的开发语言,可与 Objective-C 共同运行于 Mac OS 和 iOS 平台,用于搭建基于苹果平台的应用程序。

    34 引用 • 37 回帖 • 499 关注
  • Q&A

    提问之前请先看《提问的智慧》,好的问题比好的答案更有价值。

    6566 引用 • 29476 回帖 • 247 关注
  • jsoup

    jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址、HTML 文本内容。它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出和操作数据。

    6 引用 • 1 回帖 • 463 关注
  • GitHub

    GitHub 于 2008 年上线,目前,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。正因为这些功能所提供的便利,又经过长期的积累,GitHub 的用户活跃度很高,在开源世界里享有深远的声望,并形成了社交化编程文化(Social Coding)。

    207 引用 • 2031 回帖 • 1 关注
  • LaTeX

    LaTeX(音译“拉泰赫”)是一种基于 ΤΕΧ 的排版系统,由美国计算机学家莱斯利·兰伯特(Leslie Lamport)在 20 世纪 80 年代初期开发,利用这种格式,即使使用者没有排版和程序设计的知识也可以充分发挥由 TeX 所提供的强大功能,能在几天,甚至几小时内生成很多具有书籍质量的印刷品。对于生成复杂表格和数学公式,这一点表现得尤为突出。因此它非常适用于生成高印刷质量的科技和数学类文档。

    9 引用 • 32 回帖 • 162 关注
  • 小说

    小说是以刻画人物形象为中心,通过完整的故事情节和环境描写来反映社会生活的文学体裁。

    28 引用 • 108 回帖
  • V2EX

    V2EX 是创意工作者们的社区。这里目前汇聚了超过 400,000 名主要来自互联网行业、游戏行业和媒体行业的创意工作者。V2EX 希望能够成为创意工作者们的生活和事业的一部分。

    17 引用 • 236 回帖 • 418 关注
  • 尊园地产

    昆明尊园房地产经纪有限公司,即:Kunming Zunyuan Property Agency Company Limited(简称“尊园地产”)于 2007 年 6 月开始筹备,2007 年 8 月 18 日正式成立,注册资本 200 万元,公司性质为股份经纪有限公司,主营业务为:代租、代售、代办产权过户、办理银行按揭、担保、抵押、评估等。

    1 引用 • 22 回帖 • 685 关注
  • Linux

    Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 Unix 的多用户、多任务、支持多线程和多 CPU 的操作系统。它能运行主要的 Unix 工具软件、应用程序和网络协议,并支持 32 位和 64 位硬件。Linux 继承了 Unix 以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

    915 引用 • 931 回帖
  • Gzip

    gzip (GNU zip)是 GNU 自由软件的文件压缩程序。我们在 Linux 中经常会用到后缀为 .gz 的文件,它们就是 Gzip 格式的。现今已经成为互联网上使用非常普遍的一种数据压缩格式,或者说一种文件格式。

    9 引用 • 12 回帖 • 114 关注
  • 服务

    提供一个服务绝不仅仅是简单的把硬件和软件累加在一起,它包括了服务的可靠性、服务的标准化、以及对服务的监控、维护、技术支持等。

    41 引用 • 24 回帖 • 8 关注