Protocol Buffers 是什么
Protocol Buffers(Protobuf)是语言无关的接口定义与序列化格式:用 .proto 描述消息结构与服务方法,工具链生成各语言的代码,二进制编码比 JSON 更紧凑、解析更快。它的兼容性来自字段编号而非字段名——双方按编号解析,因此新增字段必须用新编号,废弃字段要把编号与名称放进 reserved 声明,永久禁止复用。掌握这条规则,就能在不停机、不升级全部调用方的前提下演进消息结构。
基本信息
| 定义文件 | .proto 描述消息、枚举与服务方法 |
|---|---|
| 编码特点 | 二进制、字段编号定位,体积与解析开销低于文本格式 |
| 兼容机制 | 按编号解析,字段名仅用于生成代码 |
| 演进规则 | 新增用新编号;废弃用 reserved 冻结编号与名称 |
| 生态 | 常与 gRPC 配合使用,也可单独用于消息与文件存储 |
典型使用场景
- 服务间通信:多语言服务之间用同一份 .proto 生成代码,避免手写解析
- 消息与事件:作为 Kafka 等消息队列的载荷格式,配合模式注册中心治理
- 移动端接口:体积与解析开销敏感的场景,优于文本格式
- 数据落盘:结构化数据长期保存,靠编号演进保证历史数据可读
- 配置下发:把结构化配置二进制化,减少传输体积
- 跨团队契约:接口定义集中维护,变更走评审与兼容检查
定义与演进示例
定义与演进示例
syntax = "proto3";
message Order {
string id = 1; // 编号 1 一旦发布不可更改含义
int64 total_cents = 2; // 金额用整数分,避免浮点误差
reserved 3; // 已废弃字段的编号,永久保留
reserved "legacy_no"; // 已废弃字段的名称,防止被重新启用
repeated Item items = 4; // 新增字段用新编号,旧客户端忽略即可
string channel = 5; // 可选字段默认值需与业务约定区分「未设置」
}兼容规则
| 操作 | 兼容性 | 说明 |
|---|---|---|
| 新增字段(新编号) | 兼容 | 旧数据解析时该字段取默认值 |
| 删除字段 | 需先废弃 | 保留编号与名称到 reserved,禁止复用编号 |
| 修改类型 | 多为破坏 | 如 int32 改 string 会导致解析错乱 |
| 字段改名 | 二进制兼容 | 不影响解析,但会影响生成代码与文档 |
| 枚举新增值 | 需容忍未知值 | 旧客户端遇到未知枚举值需要有默认处理分支 |
兼容规则要写进团队规范并放进流水线:用 lint 与兼容检查工具阻止复用编号、改类型等高风险改动进入主干。
proto3 中基本类型无法区分「未设置」与「默认值」:业务需要区分时使用可选字段或包装类型,否则 0 与「未填」会被混为一谈。