Protocol Buffers 序列化协议及应用

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

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,感兴趣的同学可以去下载研究一下。

替代文字

相关帖子

欢迎来到这里!

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

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

推荐标签 标签

  • 大数据

    大数据(big data)是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。

    89 引用 • 113 回帖
  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖
  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    492 引用 • 1383 回帖 • 375 关注
  • 智能合约

    智能合约(Smart contract)是一种旨在以信息化方式传播、验证或执行合同的计算机协议。智能合约允许在没有第三方的情况下进行可信交易,这些交易可追踪且不可逆转。智能合约概念于 1994 年由 Nick Szabo 首次提出。

    1 引用 • 11 回帖 • 7 关注
  • 星云链

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

    3 引用 • 16 回帖
  • Sandbox

    如果帖子标签含有 Sandbox ,则该帖子会被视为“测试帖”,主要用于测试社区功能,排查 bug 等,该标签下内容不定期进行清理。

    370 引用 • 1215 回帖 • 582 关注
  • webpack

    webpack 是一个用于前端开发的模块加载器和打包工具,它能把各种资源,例如 JS、CSS(less/sass)、图片等都作为模块来使用和处理。

    41 引用 • 130 回帖 • 295 关注
  • OAuth

    OAuth 协议为用户资源的授权提供了一个安全的、开放而又简易的标准。与以往的授权方式不同之处是 oAuth 的授权不会使第三方触及到用户的帐号信息(如用户名与密码),即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此 oAuth 是安全的。oAuth 是 Open Authorization 的简写。

    36 引用 • 103 回帖 • 9 关注
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 549 关注
  • Hibernate

    Hibernate 是一个开放源代码的对象关系映射框架,它对 JDBC 进行了非常轻量级的对象封装,使得 Java 程序员可以随心所欲的使用对象编程思维来操纵数据库。

    39 引用 • 103 回帖 • 685 关注
  • 数据库

    据说 99% 的性能瓶颈都在数据库。

    330 引用 • 614 回帖 • 1 关注
  • ZooKeeper

    ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 HBase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。

    59 引用 • 29 回帖 • 19 关注
  • OkHttp

    OkHttp 是一款 HTTP & HTTP/2 客户端库,专为 Android 和 Java 应用打造。

    16 引用 • 6 回帖 • 54 关注
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 545 关注
  • 正则表达式

    正则表达式(Regular Expression)使用单个字符串来描述、匹配一系列遵循某个句法规则的字符串。

    31 引用 • 94 回帖
  • 微信

    腾讯公司 2011 年 1 月 21 日推出的一款手机通讯软件。用户可以通过摇一摇、搜索号码、扫描二维码等添加好友和关注公众平台,同时可以将自己看到的精彩内容分享到微信朋友圈。

    129 引用 • 793 回帖 • 1 关注
  • 阿里云

    阿里云是阿里巴巴集团旗下公司,是全球领先的云计算及人工智能科技公司。提供云服务器、云数据库、云安全等云计算服务,以及大数据、人工智能服务、精准定制基于场景的行业解决方案。

    89 引用 • 345 回帖
  • PHP

    PHP(Hypertext Preprocessor)是一种开源脚本语言。语法吸收了 C 语言、 Java 和 Perl 的特点,主要适用于 Web 开发领域,据说是世界上最好的编程语言。

    164 引用 • 407 回帖 • 526 关注
  • 区块链

    区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。所谓共识机制是区块链系统中实现不同节点之间建立信任、获取权益的数学算法 。

    91 引用 • 751 回帖
  • React

    React 是 Facebook 开源的一个用于构建 UI 的 JavaScript 库。

    192 引用 • 291 回帖 • 443 关注
  • Mac

    Mac 是苹果公司自 1984 年起以“Macintosh”开始开发的个人消费型计算机,如:iMac、Mac mini、Macbook Air、Macbook Pro、Macbook、Mac Pro 等计算机。

    164 引用 • 594 回帖 • 1 关注
  • 单点登录

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

    9 引用 • 25 回帖 • 2 关注
  • Bug

    Bug 本意是指臭虫、缺陷、损坏、犯贫、窃听器、小虫等。现在人们把在程序中一些缺陷或问题统称为 bug(漏洞)。

    77 引用 • 1741 回帖
  • Sublime

    Sublime Text 是一款可以用来写代码、写文章的文本编辑器。支持代码高亮、自动完成,还支持通过插件进行扩展。

    10 引用 • 5 回帖
  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    18708 引用 • 69849 回帖
  • jQuery

    jQuery 是一套跨浏览器的 JavaScript 库,强化 HTML 与 JavaScript 之间的操作。由 John Resig 在 2006 年 1 月的 BarCamp NYC 上释出第一个版本。全球约有 28% 的网站使用 jQuery,是非常受欢迎的 JavaScript 库。

    63 引用 • 134 回帖 • 741 关注
  • 知乎

    知乎是网络问答社区,连接各行各业的用户。用户分享着彼此的知识、经验和见解,为中文互联网源源不断地提供多种多样的信息。

    10 引用 • 66 回帖 • 1 关注