Protocol Buffer 简介

Protocol Buffer 简介

Scroll Down

最近阅读 Skywalking 源码的时候发现,Skywalking Trace 的数据都是通过 protobuf 协议来通信的,在继续阅读源码前,想简单了解 Protocol Buffer

喜欢阅读英文文档的读者可以考虑直接查看官方网站:
https://developers.google.com/protocol-Buffer

什么是 Protocol Buffer

Protocol Buffer 是一种灵活、高效和自动化的序列化结构型数据的机制 --- 和 XML 相比,它更小、更快,以及更简单。我们一旦定义好了结构化数据,就可以生成出各种编程语言的源码,帮助我们轻松地从各种数据流中写入和读取该数据。甚至可以更新数据结构,而不破坏根据格式编译的已部署的项目。

XML 对比

Protocol Buffer 在序列化结构化数据方面相比于 XML 有更多的优势。

优势

Protocol Buffer:

  • 更加简单
  • 体积小 3 - 10 倍
  • 解析快 20 - 100 倍
  • 更少的二义性
  • 可生成数据访问类,更方便编程使用

我们可以用人(person)这个模型来举例,人的属性有姓名(name)和邮件(email)。如果使用 XML 来建模,结果如下:

<person>
    <name>John Niang</name>
    <email>johnniang@foxmail.com</email>
</person>

然而,对应 Protocol Buffer 的消息结构如下:

person {
    name: "John Niang"
    email: "johnniang@foxmail.com"
}

这里需要说明的是,以上代码片段仅仅是为了展示 Protocol Buffer 的消息文本结构(方便读者理解),实际上它是通过二进制格式进行传输的。有关 Protocol Buffer 的编码,后续会逐步谈到。

其中,Protocol Buffer 版本的消息长度约为 28 字节,解析耗时约为 100 - 200 纳秒。而 XML 版本的长度约为 69 字节(去除空白字符),解析耗时约 5000 - 10000 纳秒。

并且使用 Protocol Buffer 在操作该模型的时候非常方便:

cout << "Name: " << person.name() << endl;
count << "Email: " << person.email() << endl;

而使用 XML 更加复杂:

cout << "Name: "
    << person.getElementsByTagName("name")->item(0)->innerText()
    << endl;
cout << "E-mail: "
    << person.getElementsByTagName("email")->item(0)->innerText()
    << endl;

劣势

Protocol Buffer 并不总是比 XML 更好。例如, Protocol Buffer 就不太适合对标记文本文档(如 HTML)进行建模,因为将结构和文本交错是非常困难的。除此之外,XML 的结构的读和编辑对人类更加友好,从 Protocol Buffer 的原始格式来看,就不是特别友好。XML 也支持一些扩展的自定义描述,而 Protocol Buffer 仅仅对于已经定义好的结构有意义(.proto 文件)

Proto3 介绍

官方发布最新版本 3 引入了一个新的语言版本 - Protocol Buffer 语言版本 3(即 proto3),同时也在之前的语言版本(即 proto2)的基础之上新增了很多功能特性。Proto3 简化了 Protocol Buffer 语言,主要是为了易用和支持更广泛的编程语言:当前已发布版本所支持的语言有 Java、C++、Python、Java Lite、Ruby、JavaScript、Objective-C 和 C#。除此之外,我们也可以使用最新的 Go protoc 插件来生成 Go 语言对应的 proto3 源码。其他的语言正在计划支持中。

需要注意的是,两种语言版本的 API 是不完全兼容的。为了避免给老用户造成不方便,在最新的版本发布中,官方会持续支持上一个语言版本(proto2)。

proto2 和 proto3 的命名看起来似乎有些困惑,这是因为官方当初开放 Protocol Buffer 源码的时候就已经是 Google 的第二个版本了,也即是 proto2。因此,开源版本号也从 v2.0.0 开始。

Protocol Buffer 历史

有关 Protocol Buffer 的历史建议查看官方文档