跨版本运行时保证
Protobuf 语言绑定有两个组成部分:生成的代码(gencode)和为该生成代码实现通用功能的运行时库。当这两者来自不同版本的 Protobuf 时,我们就处于“跨版本运行时”的情况。
我们打算为大多数语言提供以下保证。这些是默认保证;但是,Protobuf 代码生成器和运行时的所有者可以用该语言更具体的保证来明确覆盖它们。 C++ 和 Rust 的保证比通常情况更严格,而 Python 的保证则更宽松。
超出保证范围的 Protobuf 跨版本使用是容易出错且不受支持的。版本偏差可能导致难以诊断的*偶发问题和未定义行为*,即使在源文件没有不兼容变化的情况下,它也常常*看起来*能正常工作。对于 Protobuf 来说,依赖于不受支持的 Protobuf 语言绑定的工具和服务的泛滥,会阻碍 Protobuf 团队为响应错误报告或安全漏洞而更新 Protobuf 实现。
新版生成代码 + 旧版运行时 = 绝不允许
我们可能在任何类型的版本(主版本、次版本或补丁版本)中添加新的运行时 API。该版本中的生成代码允许使用这些新的 API。其结果是,生成代码不应与比生成这些绑定所用的 protoc 和插件更旧的运行时配对。
我们会尽可能添加“毒丸”(poison pills),以防止将较新版本的生成代码与较旧版本的运行时配对的尝试。
主版本
Protobuf 为主版本实现了滑动窗口兼容性。为主版本 V(完整版本:V.x.y)生成的代码将受到主版本为 V 和 V+1 的 Protobuf 运行时的支持。
Protobuf 不支持使用版本 V 的生成代码与版本 >= V+2 的运行时,并将使用“毒丸”机制,在软件程序集尝试使用此类配置时以明确的错误消息失败。
例如
- 由 Protobuf 3.0.0 版本生成的 Java 代码将适用于 3.0.0 到 4.x.y 的运行时,但不适用于 2.0.0 到 2.x.y 或 >= 5.0.0 的运行时。
- 由 Protobuf 4.27.2 版本生成的 Java 代码将适用于 4.27.2 到 5.x.y 的运行时,但不适用于 2.0.0 到 4.27.1 或 >= 6.0.0 的运行时。
在无法维持与旧版生成代码的兼容性的情况下,可能会有例外,例如在需要更新生成代码以修复安全问题的情况下。
注意: 毒丸机制是在 Protobuf 26.0 版本中引入的。早于 4.26.0 的 Java 生成代码可能*看似*可以与比生成代码更旧的运行时一起工作。但是,新版生成代码和旧版运行时的组合可能会有严重的错误,直到运行时才会显现。
注意: C++ 和 Rust 不支持兼容性窗口,而 Python 支持更长的兼容性窗口。
次版本
在单个主运行时版本内,由旧版 protoc 生成的代码可以在新版运行时上运行。
注意: C++ 和 Rust 不支持跨次版本的兼容性。
安全例外
如果出于安全原因需要,我们保留违反上述承诺的权利。我们预计这些例外情况会很少见,但将始终把安全置于这些保证之上。例如,footmitten CVE 要求对 Java 的运行时和生成代码进行配对更新。因此,由 3.20.3(包含 footmitten 修复)生成的代码无法与 3.21.6 运行时库(早于 footmitten 修复)一起加载,从而产生了以下兼容性矩阵:
| 生成代码版本 | |||||
| 3.20.2 | 3.20.3 | 3.21.6 | 3.21.7 | ||
| 运行时 版本 | 3.20.2 | 有漏洞 | !损坏! | !有漏洞! | !损坏! |
| 3.20.3 | 有漏洞 | 正常工作 | !有漏洞! | !正常工作?! | |
| 3.21.6 | 有漏洞 | 损坏 | 有漏洞 | !损坏! | |
| 3.21.7 | 有漏洞 | 正常工作 | 有漏洞 | 正常工作 | |
- “有漏洞”表示该组合可以成功启动,但安全漏洞仍然存在。
- “正常工作”表示该组合可以成功启动并且没有该漏洞。
- “损坏”表示该组合无法成功启动。
- !粗体! 表示将新版生成代码与旧版运行时混合的配置,这些配置本就不应一起工作。
不支持多个主运行时版本共存
不支持在同一进程中并存多个主版本。
C++ 和 Rust 的特定保证
Protobuf C++ 和 Rust 不提供任何跨运行时支持,并要求在任何时候生成的代码版本和运行时版本都完全匹配。
此外,Protobuf C++ 不对任何版本(主版本、次版本或微版本)之间的 ABI 稳定性做出任何保证。
Python 的特定保证
自 3.20.0 版本以来,Protobuf Python 生成的代码变成了一个围绕嵌入式 FileDescriptorProto 的薄封装层。由于这些 proto 在极长的时间范围内都受到支持,我们通常的主版本兼容性窗口通常是不必要的。
Python 可能会在未来的特定主版本中破坏生成代码的兼容性,但这将伴随着事前的毒丸警告和错误。截至 6.32.0,所有自 3.20.0 以来生成的代码将至少被支持到 8.x.y 版本。