菜单

概述

相关源文件

Protocol Buffers (protobuf) 是 Google 的语言中立、平台中立、可扩展的结构化数据序列化机制。本文档将介绍 Protocol Buffers 系统、其架构以及代码库中的关键组件。

Protocol Buffers 允许您在 .proto 文件中定义数据结构,然后使用特殊的生成源代码,通过多种语言轻松地将结构化数据写入和读取到各种数据流中。它类似于 XML 或 JSON,但更小、更快,并且会生成原生语言绑定。

有关在应用程序中使用 Protocol Buffers 的信息,请参阅核心组件部分。

来源: src/google/protobuf/descriptor.h1-30 CONTRIBUTORS.txt1-107

系统架构

Protocol Buffers 由几个关键组件组成,它们协同工作,提供高效的数据序列化和反序列化功能。

高层架构

整体工作流程包含两个Distinct阶段

  1. 构建时.proto 文件由 Protocol Compiler (protoc) 解析,生成特定语言的代码。
  2. 运行时:应用程序使用生成的代码和运行时库来序列化/反序列化数据。

来源: src/google/protobuf/compiler/command_line_interface.cc1-107 src/google/protobuf/compiler/parser.cc1-50 src/google/protobuf/descriptor.cc1-100

编译管道

Protocol Compiler 处理 .proto 文件经过几个阶段

  1. 词法分析:将输入文件分解为标记(tokens)。
  2. 解析:将标记转换为 FileDescriptorProto(.proto 文件的 Protobuf 表示)。
  3. 符号解析:解析 DescriptorPool 中跨文件的符号。
  4. 代码生成:特定语言的生成器生成代码文件。

来源: src/google/protobuf/compiler/parser.cc100-250 src/google/protobuf/compiler/command_line_interface.cc300-350

核心组件

描述符系统

Descriptor 系统提供了一种将 Protocol Buffer 消息、字段和其他元素描述为可运行时访问的元数据的方式。

关键描述符类

  • FileDescriptor:表示一个 .proto 文件,包括其包、导入和顶级定义。
  • Descriptor:表示一个消息类型,包含其字段、嵌套类型和枚举。
  • FieldDescriptor:表示消息中的一个字段,包含类型信息和元数据。
  • EnumDescriptor/EnumValueDescriptor:表示枚举类型及其值。
  • ServiceDescriptor/MethodDescriptor:表示 RPC 的服务定义。

来源: src/google/protobuf/descriptor.h370-450 src/google/protobuf/descriptor.cc375-1000

解析器

Parser 组件将 .proto 文件文本转换为结构化的 FileDescriptorProto 对象,该对象表示文件的内容。

Parser 处理

  • 解析 proto 语法和 edition 标识符。
  • 处理 package 声明、导入和选项。
  • 解析消息、枚举、服务和字段定义。
  • 验证语法并记录错误。
  • 跟踪源位置以进行错误报告。

来源: src/google/protobuf/compiler/parser.h40-100 src/google/protobuf/compiler/parser.cc100-300

命令行界面

The CommandLineInterface 类提供了 protoc 编译器的主要入口点,处理命令行选项并协调编译过程。

主要职责

  • 处理命令行标志(例如,--proto_path--*_out
  • 管理文件导入和搜索路径。
  • 协调 FileDescriptor 的构建。
  • 调用适当的代码生成器。
  • 支持插件架构以实现可扩展性。
  • 将生成的输出写入正确的位置。

来源: src/google/protobuf/compiler/command_line_interface.h60-120 src/google/protobuf/compiler/command_line_interface.cc100-250

代码生成器

代码生成器将 FileDescriptor 对象转换为特定语言的实现代码。

The CodeGenerator 接口包括:

  • 一个 Generate() 方法,它接收一个 FileDescriptor 并生成输出文件。
  • 用于指示支持的 Protocol Buffer 特性的特性报告。
  • 用于生成器特定选项的参数解析。

生成器的源代码通常位于特定语言的目录中,例如 src/google/protobuf/compiler/cpp/

来源: src/google/protobuf/compiler/code_generator.h50-70 src/google/protobuf/compiler/code_generator.cc1-50

插件系统

Protocol Buffers 支持插件架构,可用于扩展 protoc 的自定义代码生成器。

插件接口使用 Protocol Buffer 消息进行通信:

  • CodeGeneratorRequest:包含文件描述符和参数。
  • CodeGeneratorResponse:包含生成的文件或错误消息。

插件可以用任何语言编写,并由 protoc 作为独立进程调用。

来源: src/google/protobuf/compiler/plugin.proto1-20 src/google/protobuf/compiler/plugin.cc1-50

功能系统

Protocol Buffers 具有一个特性系统,该系统允许自定义代码生成和运行时库的行为。

关键概念:

  • Editions:Protocol Buffers 的版本控制机制(例如,proto2、proto3、Editions 2023)。
  • Features:影响代码生成和运行时行为的配置选项。
  • FeatureSet:特性设置的集合。
  • FeatureResolver:根据 edition 解析特性继承和默认值。

特性可以在不同级别(文件、消息、字段)指定,并根据特定规则进行继承。

来源: src/google/protobuf/feature_resolver.cc1-30 src/google/protobuf/feature_resolver_test.cc1-60 src/google/protobuf/unittest_features.proto1-10

构建系统

Protocol Buffers 支持多种构建系统,以便在不同环境中灵活使用。

Protocol Buffers 可使用以下方式构建:

  • Bazel:Google 自有构建系统,使用 BUILD 和 WORKSPACE 文件。
  • CMake:跨平台构建系统,使用 CMakeLists.txt。
  • Make:传统的 Unix 构建系统,使用 configure 和 Makefiles。

每个构建系统都负责依赖管理、编译标志和测试基础设施。

来源: CMakeLists.txt1-100 WORKSPACE1-100 .gitignore1-100

跨平台支持

Protocol Buffers 被设计用于在各种操作系统和体系结构上工作。

平台支持包括:

  • 用于检测操作系统和 CPU 体系结构的宏
  • 用于平台特定代码的条件编译
  • 对文件 I/O、线程和内存管理的适配
  • 处理字节序和对齐差异

来源: src/google/protobuf/stubs/platform_macros.h1-115

结论

本次概述介绍了 Protocol Buffers 的关键组件和架构。该系统提供了一种强大而高效的方式,可以在多种编程语言和平台上序列化结构化数据。

通过理解核心组件——描述符系统、解析器、命令行界面、代码生成器和插件系统——开发人员可以有效地使用 Protocol Buffers 并根据自身特定需求对其进行扩展。

有关特定组件的更多详细信息,请参阅本文档的相应部分。