From 3e83e6d7f8976a2fb6ea6ce2040602e18d90ba8b Mon Sep 17 00:00:00 2001 From: YuCheng Hu Date: Mon, 30 Nov 2020 09:38:10 -0500 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=8C=96=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=20Protocol=20Buffers=20=E7=9A=84=E6=96=87=E6=A1=A3=E7=BB=93?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _sidebar.md | 1 + .../_images/protocol-buffers-logo.jpg | Bin 0 -> 27912 bytes .../protocol-buffers-serialization.png | Bin 0 -> 33303 bytes protocol-buffers/developer_guide.adoc | 210 ++++++++++++++++ protocol-buffers/index.md | 236 ++++++++++++++++++ 5 files changed, 447 insertions(+) create mode 100644 protocol-buffers/_images/protocol-buffers-logo.jpg create mode 100644 protocol-buffers/_images/protocol-buffers-serialization.png create mode 100644 protocol-buffers/developer_guide.adoc create mode 100644 protocol-buffers/index.md diff --git a/_sidebar.md b/_sidebar.md index 9288393..15e7afa 100644 --- a/_sidebar.md +++ b/_sidebar.md @@ -8,6 +8,7 @@ - 其他小工具 - [JWT](jwt/README.md) - [MessagePack](message-pack/index.md) + - [Protocol Buffers](protocol-buffers/index.md) - [Awesome docsify](awesome.md) - [Changelog](changelog.md) \ No newline at end of file diff --git a/protocol-buffers/_images/protocol-buffers-logo.jpg b/protocol-buffers/_images/protocol-buffers-logo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..aa65135cce988ba0c1fdb61150ef662687d35e42 GIT binary patch literal 27912 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 z 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 G!~PG@R>;o) literal 0 HcmV?d00001 diff --git a/protocol-buffers/developer_guide.adoc b/protocol-buffers/developer_guide.adoc new file mode 100644 index 0000000..aa833f9 --- /dev/null +++ b/protocol-buffers/developer_guide.adoc @@ -0,0 +1,210 @@ += Developer Guide +YuCheng Hu +:doctype: book +:page-layout: docs +:page-description: Protocol Buffers +:page-keywords: Protocol Buffers + +:imagesdir: images +:includedir: _includes + +中文标题【开发者指南】 + +欢迎来到 protocol buffers 的开发者指南。protocol buffers 是一个语言中立,平台中立针对通讯协议,数据存储和其他领域中对结构化数据进行序列化的扩展方法。 + +本文档主要针对的是 Java,C++ 或 Python 的开发人员希望在开发的应用程序中使用 Protocol Buffers。这个有关 Protocol Buffers 摘要性的介绍将会告诉你如何开始使用 Protocol Buffers。 +如果你希望更加深入的了解有关 Protocol Buffers 的内容,你可以进入 tutorials 或者 protocol buffer encoding 页面来详细了解。 + +有关 API 的参考文档,请参考页面:reference documentation 这里提供了所有这 3 种语言的参考,同时也针对 .proto language 和 style 提供相关的指南。 + +== 什么是 Protocol Buffers +Protocol buffers 是对结构化数据序列化的一个灵活,高效,自动化工具 —— 你可以将 Protocol buffers 想象成 XML,但是体积更小,更快也更加简单。 + +你可以自己定义你的结构化数据,然后你可以使用特定的代码生成工具来非常容易对你的结构化数据进行读取和写入。这些数据的读取和写入可以是一系列的数据流和使用不同的计算机程序语言。 +你甚至可以在不对已经部署的程序进行破坏的情况下更新你的数据结构。 + +== Protocol Buffers 是如何进行工作的 +你需要制定你希望如何将你的数据进行序列化。你是通过 proto 文件来定义你的消息结构化数据的。 + +每一 protocol buffer message 是一个小的信息记录逻辑,这个消息中包含有一系列的名字,变量对照序列。 +下面是一些基本的.proto 文件,这些文件中定义了一个消息,这个消息包含有一个 person 信息: + +[source] +---- +message Person { + required string name = 1; + required int32 id = 2; + optional string email = 3; + + enum PhoneType { + MOBILE = 0; + HOME = 1; + WORK = 2; + } + + message PhoneNumber { + required string number = 1; + optional PhoneType type = 2 [default = HOME]; + } + + repeated PhoneNumber phone = 4; +} +---- + +通过上面你可以看到这个消息的格式非常简单—— 每一个消息类型都有一个或者多个唯一进行编号的字段,每一个字段包含有一个名字和变量类型。 + +变量可以为数字(整形或者浮点型)(numbers),布尔类型(booleans),字符串(strings),原生二进制(raw bytes)甚至其他的 protocol buffer 消息类型,能够允许你分级的结构化你的数据。 + +你可以将字段指定为可选字段(optional fields),必须字段(required fields)和重复字段(repeated fields)。你可以从下面的 Protocol Buffer Language Guide 页面中找到更多有关 .proto 的定义。 + +一旦你成功定义了你的消息,你可以针对你使用的语言使用你定义的 .proto 来运行 protocol buffer 编译器(protocol buffer compiler)来生成数据访问类。 + +针对每一个字段,在数据访问类中提供了简单的访问方法(例如 name() 和 set_name())和序列化到原生 2 进制数据和从原生 2 进制数据反序列化的方法。 + +针对上面的定义,如果你现在使用的是 C++ 语言的话,当你把消息定义进行编译后,你将会得到一个称为 Person 的类。 +,对数据进行序列化和从序列化的数据中(protocol buffer 消息)重新获得 Person 数据。 + +然后你可以写一些类似 Person person; 的代码。 + +[source,CPP] +---- +Person person; +person.set_name("John Doe"); +person.set_id(1234); +person.set_email("jdoe@example.com"); +fstream output("myfile", ios::out | ios::binary); +person.SerializeToOstream(&output); +---- + +随后,你可以对消息进行读取: + +[source,CPP] +---- +fstream input("myfile", ios::in | ios::binary); +Person person; +person.ParseFromIstream(&input); +cout << "Name: " << person.name() << endl; +cout << "E-mail: " << person.email() << endl; +---- + +你可以向你的消息中添加新的字段而不会损坏老的消息。这是因为在老的消息处理中,针对新的字段是完全忽略掉的。因此,如果你在你的通讯协议中使用 protocol buffers 为数据结构的话, +你可以对你的协议和消息进行扩展而不需要担心老的代码没有办法编译通过,或者损坏老的代码。 + +你可以访问 API Reference section 页面中的内容来了解完整 protocol buffer 代码的生成和使用。 + +你也可以在 Protocol Buffer Encoding 页面中了解更多protocol buffer 消息是如何进行编码的。 + +== 为什么不使用 XML +针对 XML 来说 Protocol Buffers 具有更多的优势来对序列化结构数据。 + +* 更加简单 +* 小于 XML 3 到 10 倍 +* 快于 XML 20 到 100 倍 +* 松耦合 +* 使用程序工具来创建数据访问类,使数访问类更加简单 +* 假设,你需要讲 person 这个数据进行定义,在 XML 你需要使用: + +[source,XML] +---- + + John Doe + jdoe@example.com + +---- + +来进行定义。 + +在 Protocol Buffers 中针对上面的消息文本化(text format)后显示为: + +[source] +---- +# Textual representation of a protocol buffer. +# This is *not* the binary format used on the wire. +person { + name: "John Doe" + email: "jdoe@example.com" +} +---- + +当上面的消息被编码为 Protocol Buffer 二进制格式(binary format)上面的文字可能小于 28 bytes,并且可能需要 100-200 纳秒(nanoseconds)来进行处理。 + +我们将上面转换为可以人为读取的目的主要是为进行调试和编辑。 + +如果你使用 XML 的话,上面的信息至少需要 69 bytes (你需要删除所有的空格),同时你需要 5,000-10,000 纳秒(nanoseconds)来进行处理。 + +同时,对 protocol buffer 进行操作也是非常容易的: + +[source,CPP] +---- +cout << "Name: " << person.name() << endl; +cout << "E-mail: " << person.email() << endl; +---- + +如果使用的是 XML 的话,你需要进行下面的操作: + +[source,CPP] +---- +cout << "Name: " + << person.getElementsByTagName("name")->item(0)->innerText() + << endl; +cout << "E-mail: " + << person.getElementsByTagName("email")->item(0)->innerText() + << endl; +---- + +但是,protocol buffers 并不是任何时候都会比 XML 好。例如,针对基于文本的标记语言(例如,XML),protocol buffers 就不是一个很好的选项, +因为你不能使用 protocol buffer 更好的在文档中进行交换。更主要的是 HTML 是人类可以阅读和编辑的。protocol buffer 也不是不可以人为的读取,但是针对原生的 protocol buffer 格式是没有办法人为进行读取和编辑的。 + +XML 与 HTML 一样,在某种程度上是一种自我描述数据。protocol buffer 只针对你在 .proto 文件中描述的内容进行表达。 + +== 看起来像一个解决方案,我应该如何开始呢 +Download the package – 这包中含有针对 Java, Python, 和 C++ protocol buffer 编译器源代码,和你需要进行 I/O 和测试的类。希望对你的编译器进行编译和构建,请参考代码中的 README 文件。 + +一旦你完成了所有的设置,请参考 tutorial 页面中的内容来选择你需要的语言——这个能够帮助你使用 protocol buffer 创建一个简单的应用程序。 + +== 介绍 proto3 +在我们最新的 version 3 发行版 中推出了新的语言版本 —— Protocol Buffers language version 3(另称 proto3),在这个版本中针对我们已经存在的语言版本(proto2)使用了一些新的特性。 + +Proto3 简化了 protocol buffer 语言,使其更加容易使用并且能够支持更多的语言:我们当前发行的 proto3 能够让你创建 Java, C++, Python, Java Lite, Ruby, JavaScript, Objective-C, and C#。 + +另外你也可以通过使用 Go protoc 插件来用 proto3 创建 Go 代码,这个插件你可以到 golang/protobuf Github 中下载到。更多的语言还在逐步进行支持中。 + +请注意,这 2 个版本的 API 并不是完全兼容的。为了照顾还在使用老版本的用户,我们将会在新的 protocol buffers 发行中同时支持老的版本。 + +你可以在下面的发行日志(release notes)查看 2 个版本的主要不同。有关 proto3 的句法,请参考 Proto3 Language Guide 中的内容,针对 proto3 的完整文档还没有编写完成,将会随后推出。 + +看起来 proto2 和 proto3 可能会产生一些混淆,这是因为原始的开源 protocol buffers 实际上是 Google 内部语言的第二个版本,同时我们的开源版本也是从 v2.0.0 开始的。 +简单来说就是 proto 最开始的版本是 Google 内部使用的,在 proto 第二个版本的时候,Google 决定进行开源了,所以开源的 proto 是从 proto2 开始的。 + +== 一个简短的历史 +Protocol buffers 最开始是在 Google 内部进行开发的,用于处理在索引服务器上请求/响应(request/response)的协议。 + +在 Protocol buffers 之前,针对请求和响应,使用的是 marshalling/unmarshalling,这个能够支持一系列的协议。但是结果看起来却是非常的难看,例如: +[source] +---- +if (version == 3) { + ... +} else if (version > 4) { + if (version == 5) { + ... + } + ... +} +---- + +明确格式化的的协议也使新版本的协议更加难以推出,这是因为开发者必须能够了解老协议在服务器之间是如何进行处理的,同时也需要了解新的协议。只有对新老协议都有所了解后才能逐步使用新的协议替换老的协议。 + +Protocol buffers 被用来设计解决上面的很多问题: + +* 新的字段比较能够容易的进行定义,中级服务器不需要对数据进行检查,直接对数据进行处理,同时也可以直接传输数据而不需要了解数据是如何进行定义的。 +* 格式使用自描述,能够更加容易支持更多的语言(C++,Java 等)。 + +但是,用户还是需要手动书写他们自己的处理diam。 + +作为系统的进化来说,它获得了许多其他的特性和用途: + +* 自动生成序列化和反序列化代码而避免手动书写这些代码。 +* 除了开始使用短期RPC(远程过程调用)请求,人们开始使用 protocol buffers 作为高效的自描述结构化数据格式(主要针对数据短期存在,例如在 Bigtable)。 +* 服务器RPC接口开始被声明为协议文件的一部分,协议编译器生成根类,用户可以通过服务器接口的实现和重载它们。 + +Protocol buffers 在 Google 中成为针对数据的通用语言—— 随着时间的流逝,在 Google 内部已经有超过 348,952 .proto 文件被定义。这些被用在 RPC 系统和存储系统中存储数据。 diff --git a/protocol-buffers/index.md b/protocol-buffers/index.md new file mode 100644 index 0000000..9b29990 --- /dev/null +++ b/protocol-buffers/index.md @@ -0,0 +1,236 @@ += Protocol Buffers 文档 + +Protocol Buffers 相关文档的内容。 + +![protocol-buffers-logo](_images/protocol-buffers-logo.jpg) + +## Protocol Buffers 简介 +如果你在互联网上搜索的话,你可能会看到下面的说明文字。 + + +> Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。 +> 他们用于 RPC 系统和持续数据存储系统。 +> Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。 +> 它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。 +> 目前提供了 C++、Java、Python 三种语言的 API。 + + +我们是在实际的数据处理的时候,需要使用 JSON 来序列化数据,但是又考虑到 JSON 在传输的时候数据过大,同时还有很多并不需要的垃圾文件。 +我们才考虑到了 Protocol Buffer 提供的功能。 + + +## Protocol Buffers 文档快速导航 += Developer Guide +YuCheng Hu +:doctype: book +:page-layout: docs +:page-description: Protocol Buffers +:page-keywords: Protocol Buffers + +:imagesdir: images +:includedir: _includes + +中文标题【开发者指南】 + +欢迎来到 protocol buffers 的开发者指南。protocol buffers 是一个语言中立,平台中立针对通讯协议,数据存储和其他领域中对结构化数据进行序列化的扩展方法。 + +本文档主要针对的是 Java,C++ 或 Python 的开发人员希望在开发的应用程序中使用 Protocol Buffers。这个有关 Protocol Buffers 摘要性的介绍将会告诉你如何开始使用 Protocol Buffers。 +如果你希望更加深入的了解有关 Protocol Buffers 的内容,你可以进入 tutorials 或者 protocol buffer encoding 页面来详细了解。 + +有关 API 的参考文档,请参考页面:reference documentation 这里提供了所有这 3 种语言的参考,同时也针对 .proto language 和 style 提供相关的指南。 + +== 什么是 Protocol Buffers +Protocol buffers 是对结构化数据序列化的一个灵活,高效,自动化工具 —— 你可以将 Protocol buffers 想象成 XML,但是体积更小,更快也更加简单。 + +你可以自己定义你的结构化数据,然后你可以使用特定的代码生成工具来非常容易对你的结构化数据进行读取和写入。这些数据的读取和写入可以是一系列的数据流和使用不同的计算机程序语言。 +你甚至可以在不对已经部署的程序进行破坏的情况下更新你的数据结构。 + +== Protocol Buffers 是如何进行工作的 +你需要制定你希望如何将你的数据进行序列化。你是通过 proto 文件来定义你的消息结构化数据的。 + +每一 protocol buffer message 是一个小的信息记录逻辑,这个消息中包含有一系列的名字,变量对照序列。 +下面是一些基本的.proto 文件,这些文件中定义了一个消息,这个消息包含有一个 person 信息: + +[source] +---- +message Person { + required string name = 1; + required int32 id = 2; + optional string email = 3; + + enum PhoneType { + MOBILE = 0; + HOME = 1; + WORK = 2; + } + + message PhoneNumber { + required string number = 1; + optional PhoneType type = 2 [default = HOME]; + } + + repeated PhoneNumber phone = 4; +} +---- + +通过上面你可以看到这个消息的格式非常简单—— 每一个消息类型都有一个或者多个唯一进行编号的字段,每一个字段包含有一个名字和变量类型。 + +变量可以为数字(整形或者浮点型)(numbers),布尔类型(booleans),字符串(strings),原生二进制(raw bytes)甚至其他的 protocol buffer 消息类型,能够允许你分级的结构化你的数据。 + +你可以将字段指定为可选字段(optional fields),必须字段(required fields)和重复字段(repeated fields)。你可以从下面的 Protocol Buffer Language Guide 页面中找到更多有关 .proto 的定义。 + +一旦你成功定义了你的消息,你可以针对你使用的语言使用你定义的 .proto 来运行 protocol buffer 编译器(protocol buffer compiler)来生成数据访问类。 + +针对每一个字段,在数据访问类中提供了简单的访问方法(例如 name() 和 set_name())和序列化到原生 2 进制数据和从原生 2 进制数据反序列化的方法。 + +针对上面的定义,如果你现在使用的是 C++ 语言的话,当你把消息定义进行编译后,你将会得到一个称为 Person 的类。 +,对数据进行序列化和从序列化的数据中(protocol buffer 消息)重新获得 Person 数据。 + +然后你可以写一些类似 Person person; 的代码。 + +[source,CPP] +---- +Person person; +person.set_name("John Doe"); +person.set_id(1234); +person.set_email("jdoe@example.com"); +fstream output("myfile", ios::out | ios::binary); +person.SerializeToOstream(&output); +---- + +随后,你可以对消息进行读取: + +[source,CPP] +---- +fstream input("myfile", ios::in | ios::binary); +Person person; +person.ParseFromIstream(&input); +cout << "Name: " << person.name() << endl; +cout << "E-mail: " << person.email() << endl; +---- + +你可以向你的消息中添加新的字段而不会损坏老的消息。这是因为在老的消息处理中,针对新的字段是完全忽略掉的。因此,如果你在你的通讯协议中使用 protocol buffers 为数据结构的话, +你可以对你的协议和消息进行扩展而不需要担心老的代码没有办法编译通过,或者损坏老的代码。 + +你可以访问 API Reference section 页面中的内容来了解完整 protocol buffer 代码的生成和使用。 + +你也可以在 Protocol Buffer Encoding 页面中了解更多protocol buffer 消息是如何进行编码的。 + +== 为什么不使用 XML +针对 XML 来说 Protocol Buffers 具有更多的优势来对序列化结构数据。 + +* 更加简单 +* 小于 XML 3 到 10 倍 +* 快于 XML 20 到 100 倍 +* 松耦合 +* 使用程序工具来创建数据访问类,使数访问类更加简单 +* 假设,你需要讲 person 这个数据进行定义,在 XML 你需要使用: + +[source,XML] +---- + + John Doe + jdoe@example.com + +---- + +来进行定义。 + +在 Protocol Buffers 中针对上面的消息文本化(text format)后显示为: + +[source] +---- +# Textual representation of a protocol buffer. +# This is *not* the binary format used on the wire. +person { + name: "John Doe" + email: "jdoe@example.com" +} +---- + +当上面的消息被编码为 Protocol Buffer 二进制格式(binary format)上面的文字可能小于 28 bytes,并且可能需要 100-200 纳秒(nanoseconds)来进行处理。 + +我们将上面转换为可以人为读取的目的主要是为进行调试和编辑。 + +如果你使用 XML 的话,上面的信息至少需要 69 bytes (你需要删除所有的空格),同时你需要 5,000-10,000 纳秒(nanoseconds)来进行处理。 + +同时,对 protocol buffer 进行操作也是非常容易的: + +[source,CPP] +---- +cout << "Name: " << person.name() << endl; +cout << "E-mail: " << person.email() << endl; +---- + +如果使用的是 XML 的话,你需要进行下面的操作: + +[source,CPP] +---- +cout << "Name: " + << person.getElementsByTagName("name")->item(0)->innerText() + << endl; +cout << "E-mail: " + << person.getElementsByTagName("email")->item(0)->innerText() + << endl; +---- + +但是,protocol buffers 并不是任何时候都会比 XML 好。例如,针对基于文本的标记语言(例如,XML),protocol buffers 就不是一个很好的选项, +因为你不能使用 protocol buffer 更好的在文档中进行交换。更主要的是 HTML 是人类可以阅读和编辑的。protocol buffer 也不是不可以人为的读取,但是针对原生的 protocol buffer 格式是没有办法人为进行读取和编辑的。 + +XML 与 HTML 一样,在某种程度上是一种自我描述数据。protocol buffer 只针对你在 .proto 文件中描述的内容进行表达。 + +== 看起来像一个解决方案,我应该如何开始呢 +Download the package – 这包中含有针对 Java, Python, 和 C++ protocol buffer 编译器源代码,和你需要进行 I/O 和测试的类。希望对你的编译器进行编译和构建,请参考代码中的 README 文件。 + +一旦你完成了所有的设置,请参考 tutorial 页面中的内容来选择你需要的语言——这个能够帮助你使用 protocol buffer 创建一个简单的应用程序。 + +== 介绍 proto3 +在我们最新的 version 3 发行版 中推出了新的语言版本 —— Protocol Buffers language version 3(另称 proto3),在这个版本中针对我们已经存在的语言版本(proto2)使用了一些新的特性。 + +Proto3 简化了 protocol buffer 语言,使其更加容易使用并且能够支持更多的语言:我们当前发行的 proto3 能够让你创建 Java, C++, Python, Java Lite, Ruby, JavaScript, Objective-C, and C#。 + +另外你也可以通过使用 Go protoc 插件来用 proto3 创建 Go 代码,这个插件你可以到 golang/protobuf Github 中下载到。更多的语言还在逐步进行支持中。 + +请注意,这 2 个版本的 API 并不是完全兼容的。为了照顾还在使用老版本的用户,我们将会在新的 protocol buffers 发行中同时支持老的版本。 + +你可以在下面的发行日志(release notes)查看 2 个版本的主要不同。有关 proto3 的句法,请参考 Proto3 Language Guide 中的内容,针对 proto3 的完整文档还没有编写完成,将会随后推出。 + +看起来 proto2 和 proto3 可能会产生一些混淆,这是因为原始的开源 protocol buffers 实际上是 Google 内部语言的第二个版本,同时我们的开源版本也是从 v2.0.0 开始的。 +简单来说就是 proto 最开始的版本是 Google 内部使用的,在 proto 第二个版本的时候,Google 决定进行开源了,所以开源的 proto 是从 proto2 开始的。 + +== 一个简短的历史 +Protocol buffers 最开始是在 Google 内部进行开发的,用于处理在索引服务器上请求/响应(request/response)的协议。 + +在 Protocol buffers 之前,针对请求和响应,使用的是 marshalling/unmarshalling,这个能够支持一系列的协议。但是结果看起来却是非常的难看,例如: +[source] +---- +if (version == 3) { + ... +} else if (version > 4) { + if (version == 5) { + ... + } + ... +} +---- + +明确格式化的的协议也使新版本的协议更加难以推出,这是因为开发者必须能够了解老协议在服务器之间是如何进行处理的,同时也需要了解新的协议。只有对新老协议都有所了解后才能逐步使用新的协议替换老的协议。 + +Protocol buffers 被用来设计解决上面的很多问题: + +* 新的字段比较能够容易的进行定义,中级服务器不需要对数据进行检查,直接对数据进行处理,同时也可以直接传输数据而不需要了解数据是如何进行定义的。 +* 格式使用自描述,能够更加容易支持更多的语言(C++,Java 等)。 + +但是,用户还是需要手动书写他们自己的处理diam。 + +作为系统的进化来说,它获得了许多其他的特性和用途: + +* 自动生成序列化和反序列化代码而避免手动书写这些代码。 +* 除了开始使用短期RPC(远程过程调用)请求,人们开始使用 protocol buffers 作为高效的自描述结构化数据格式(主要针对数据短期存在,例如在 Bigtable)。 +* 服务器RPC接口开始被声明为协议文件的一部分,协议编译器生成根类,用户可以通过服务器接口的实现和重载它们。 + +Protocol buffers 在 Google 中成为针对数据的通用语言—— 随着时间的流逝,在 Google 内部已经有超过 348,952 .proto 文件被定义。这些被用在 RPC 系统和存储系统中存储数据。 + + +![protocol-buffers-serialization](_images/protocol-buffers-serialization.png) +image::protocol-buffers-serialization.png[]