首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Protocol Buffers (Protobuf) 详解

Protocol Buffers (Protobuf) 详解

作者头像
木易士心
发布2025-11-30 10:20:49
发布2025-11-30 10:20:49
30
举报

Protocol Buffers (Protobuf) 详解

1. 什么是 Protocol Buffers?

Protocol Buffers(简称 Protobuf)是 Google 开发的一种语言无关、平台无关、可扩展的序列化数据结构的机制。它比 XML 和 JSON 更小、更快、更简单。

2. 核心特性

2.1优点
  • 高效性:二进制格式,体积小,序列化/反序列化速度快
  • 跨语言:支持多种编程语言
  • 向前/向后兼容:通过字段编号机制实现
  • 代码生成:自动生成数据访问类
  • 结构化数据:强类型定义
2.2 缺点
  • 可读性差:二进制格式不易阅读
  • 需要预编译:需要预定义 .proto 文件

3. 基本语法

3.1 基本消息定义
代码语言:javascript
复制
syntax = "proto3";

message Person {
  string name = 1;
  int32 id = 2;
  string email = 3;
  
  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }
  
  message PhoneNumber {
    string number = 1;
    PhoneType type = 2;
  }
  
  repeated PhoneNumber phones = 4;
}
3.2 字段规则
  • singular: 单个值(默认)
  • repeated: 数组/列表
  • map<K, V>: 键值对
3.3 数据类型

.proto 类型

C++ 类型

Java 类型

Python 类型

double

double

double

float

float

float

float

float

int32

int32

int

int

int64

int64

long

int/long

bool

bool

boolean

bool

string

string

String

str

bytes

string

ByteString

bytes

4. 版本差异

proto2 vs proto3
代码语言:javascript
复制
// proto2
syntax = "proto2";
message Example {
  required string name = 1;    // 必须字段
  optional int32 id = 2;       // 可选字段
  repeated string emails = 3;  // 重复字段
}

// proto3
syntax = "proto3";
message Example {
  string name = 1;            // 默认都是可选
  int32 id = 2;
  repeated string emails = 3;
}

5. 高级特性

5.1 Oneof
代码语言:javascript
复制
message SampleMessage {
  oneof test_oneof {
    string name = 1;
    int32 id = 2;
  }
}
5.2 Map
代码语言:javascript
复制
message Product {
  map<string, string> properties = 1;
}
5.3 嵌套消息
代码语言:javascript
复制
message Outer {
  message Inner {
    string text = 1;
  }
  Inner inner = 1;
}
5.4 导入其他文件
代码语言:javascript
复制
import "other.proto";
5.5 包和命名空间
代码语言:javascript
复制
package my.package;

// Java 特定选项
option java_package = "com.example.generated";
option java_outer_classname = "ExampleProto";

6. 实际应用示例

6.1 完整的 .proto 文件
代码语言:javascript
复制
syntax = "proto3";

package tutorial;

option java_package = "com.example.tutorial";
option java_outer_classname = "AddressBookProtos";

message Person {
  string name = 1;
  int32 id = 2;
  string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    string number = 1;
    PhoneType type = 2;
  }

  repeated PhoneNumber phones = 4;
}

message AddressBook {
  repeated Person people = 1;
}
6.2 Python 使用示例
代码语言:javascript
复制
import addressbook_pb2

# 创建消息
person = addressbook_pb2.Person()
person.id = 1234
person.name = "John Doe"
person.email = "jdoe@example.com"

phone = person.phones.add()
phone.number = "555-4321"
phone.type = addressbook_pb2.Person.HOME

# 序列化
serialized_data = person.SerializeToString()

# 反序列化
new_person = addressbook_pb2.Person()
new_person.ParseFromString(serialized_data)

print(f"Name: {new_person.name}")
print(f"Email: {new_person.email}")
6.3 Java 使用示例
代码语言:javascript
复制
// 创建 Builder
Person person = Person.newBuilder()
    .setId(1234)
    .setName("John Doe")
    .setEmail("jdoe@example.com")
    .addPhones(
        Person.PhoneNumber.newBuilder()
            .setNumber("555-4321")
            .setType(Person.PhoneType.HOME)
            .build())
    .build();

// 序列化
byte[] serializedData = person.toByteArray();

// 反序列化
Person newPerson = Person.parseFrom(serializedData);

System.out.println("Name: " + newPerson.getName());
System.out.println("Email: " + newPerson.getEmail());

7. 编译和使用

7.1 安装编译器
代码语言:javascript
复制
# 下载 protoc 编译器
# 或使用包管理器安装
7.2 编译 .proto 文件
代码语言:javascript
复制
# 生成 Java 代码
protoc --java_out=. addressbook.proto

# 生成 Python 代码
protoc --python_out=. addressbook.proto

# 生成多种语言
protoc --java_out=. --python_out=. --cpp_out=. addressbook.proto

8. 最佳实践

8.1 字段编号
  • 使用 1-15 作为常用字段(占用 1 字节)
  • 16-2047 作为不常用字段
  • 不要随意更改字段编号
8.2 向后兼容
  • 不要删除已使用的字段编号
  • 新字段使用新的编号
  • 已删除的字段可添加 reserved 声明
代码语言:javascript
复制
message Foo {
  reserved 2, 15, 9 to 11;
  reserved "foo", "bar";
}
8.3 版本管理
  • 在文件名或包名中包含版本信息
  • 使用语义化版本控制

9. 与其他序列化格式对比

特性

Protobuf

JSON

XML

大小

很大

速度

很慢

可读性

类型安全

跨语言

优秀

优秀

优秀

10. 使用场景

  • 微服务通信:gRPC 的默认序列化格式
  • 数据存储:高效存储结构化数据
  • 配置文件:强类型的配置定义
  • API 设计:定义清晰的接口契约

Protobuf 在现代分布式系统中扮演着重要角色,特别是在性能要求高、需要跨语言协作的场景中表现出色。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-11-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Protocol Buffers (Protobuf) 详解
    • 1. 什么是 Protocol Buffers?
    • 2. 核心特性
      • 2.1优点
      • 2.2 缺点
    • 3. 基本语法
      • 3.1 基本消息定义
      • 3.2 字段规则
      • 3.3 数据类型
    • 4. 版本差异
      • proto2 vs proto3
    • 5. 高级特性
      • 5.1 Oneof
      • 5.2 Map
      • 5.3 嵌套消息
      • 5.4 导入其他文件
      • 5.5 包和命名空间
    • 6. 实际应用示例
      • 6.1 完整的 .proto 文件
      • 6.2 Python 使用示例
      • 6.3 Java 使用示例
    • 7. 编译和使用
      • 7.1 安装编译器
      • 7.2 编译 .proto 文件
    • 8. 最佳实践
      • 8.1 字段编号
      • 8.2 向后兼容
      • 8.3 版本管理
    • 9. 与其他序列化格式对比
    • 10. 使用场景
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档