还在用XML和JSON?为什么Google的Protocol Buffers能快10倍
作者:佚名 时间:2025-11-17 06:58
字号
@TOC
Protocol Buffers (Protobuf) 详解
1. 什么是 Protocol Buffers?
Protocol Buffers(简称 Protobuf)是 Google 开发的一种语言无关、平台无关、可扩展的序列化数据结构的机制。它比 XML 和 JSON 更小、更快、更简单。
2. 核心特性
2.1优点
2.2 缺点
3. 基本语法
3.1 基本消息定义
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 字段规则
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
// 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
message SampleMessage {
oneof test_oneof {
string name = 1;
int32 id = 2;
}
}
5.2 Map
message Product {
map properties = 1;
}
5.3 嵌套消息
message Outer {
message Inner {
string text = 1;
}
Inner inner = 1;
}
5.4 导入其他文件
import "other.proto";
5.5 包和命名空间
package my.package;
// Java 特定选项
option java_package = "com.example.generated";
option java_outer_classname = "ExampleProto";
6. 实际应用示例
6.1 完整的 .proto 文件
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 使用示例
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 使用示例
// 创建 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 安装编译器
# 下载 protoc 编译器
# 或使用包管理器安装
7.2 编译 .proto 文件
# 生成 Java 代码
protoc --java_out=. addressbook.proto
# 生成 Python 代码
protoc --python_out=. addressbook.proto
# 生成多种语言
protoc --java_out=. --python_out=. --cpp_out=. addressbook.proto
8. 最佳实践
8.1 字段编号
8.2 向后兼容
message Foo {
reserved 2, 15, 9 to 11;
reserved "foo", "bar";
}
8.3 版本管理
9. 与其他序列化格式对比
特性 Protobuf JSON XML大小
很大
速度
很慢
可读性
类型安全
跨语言
优秀
优秀
优秀
10. 使用场景
Protobuf 在现代分布式系统中扮演着重要角色,特别是在性能要求高、需要跨语言协作的场景中表现出色。
责任编辑:CQITer新闻报料:400-888-8888 本站原创,未经授权不得转载
继续阅读



