前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Google 序列化神器 Protocol Buffer 学习指南

Google 序列化神器 Protocol Buffer 学习指南

原创
作者头像
Michel_Rolle
发布2024-06-17 22:11:19
7250
发布2024-06-17 22:11:19

简介

在现代软件开发中,数据的高效传输和存储是一个关键问题。Google 开发的 Protocol Buffer(简称 Protobuf)作为一种语言中立、平台无关、可扩展的机制,用于高效地序列化结构化数据。它比 XML 或 JSON 更加紧凑和高效,非常适合需要高性能和小体积的场景。

本文将详细介绍 Protobuf 的概念、使用方法以及一些高级特性,帮助读者快速掌握这一强大的工具。

为什么选择 Protobuf

  1. 性能高:Protobuf 使用二进制格式进行数据序列化,解析速度比 XML 和 JSON 快很多。
  2. 数据体积小:相比 XML 和 JSON,Protobuf 序列化后的数据体积更小,适合带宽受限的场景。
  3. 跨语言支持:Protobuf 支持多种编程语言,包括但不限于 C++, Java, Python, Go 等。
  4. 向后兼容:Protobuf 允许你在不破坏现有数据格式的前提下对消息进行扩展,非常适合需要频繁迭代和升级的系统。

安装与环境配置

要开始使用 Protobuf,需要安装 Protocol Buffers 编译器 protoc。以下是一些主要平台的安装方法:

在 macOS 上

使用 Homebrew 安装:

代码语言:javascript
复制
brew install protobuf
在 Ubuntu 上

使用 apt-get 安装:

代码语言:javascript
复制
sudo apt-get install -y protobuf-compiler
在 Windows 上

下载预编译的二进制文件,并将其添加到系统路径中。下载地址:Protocol Buffers Releases

定义 Protocol Buffer 消息

使用 .proto 文件定义数据结构,以下是一个简单的例子:

代码语言:javascript
复制
syntax = "proto3";

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

上述代码定义了一个 Person 消息,包含三个字段:nameidemailsyntax = "proto3"; 表示我们使用的是 Protobuf 的第三版语法。

编译 .proto 文件

编译 .proto 文件生成相应语言的代码。假设我们有一个 addressbook.proto 文件:

代码语言:javascript
复制
protoc --java_out=. addressbook.proto

上述命令会在当前目录生成 Java 文件。如果你需要生成其他语言的代码,可以指定对应的参数,比如 --python_out=. 生成 Python 代码。

使用生成的代码

以 Java 为例,假设我们已经生成了 Person.java,可以使用如下代码进行数据序列化和反序列化:

序列化
代码语言:javascript
复制
Person person = Person.newBuilder()
    .setName("John Doe")
    .setId(1234)
    .setEmail("john.doe@example.com")
    .build();

FileOutputStream output = new FileOutputStream("person.ser");
person.writeTo(output);
output.close();
反序列化
代码语言:javascript
复制
FileInputStream input = new FileInputStream("person.ser");
Person person = Person.parseFrom(input);
input.close();

System.out.println("Name: " + person.getName());
System.out.println("ID: " + person.getId());
System.out.println("Email: " + person.getEmail());

Protobuf 高级特性

可选和重复字段

Protobuf 支持可选和重复字段,使用 optionalrepeated 关键字:

代码语言:javascript
复制
message Contact {
  string name = 1;
  optional string email = 2;
  repeated string phone = 3;
}

optional 字段可以有也可以没有,repeated 字段则是一个数组,可以包含零个或多个值。

嵌套消息

Protobuf 允许在消息中嵌套其他消息:

代码语言:javascript
复制
message AddressBook {
  repeated Person people = 1;
}

message Person {
  string name = 1;
  int32 id = 2;
  string email = 3;
}
枚举类型

Protobuf 支持枚举类型,用于定义一组命名值:

代码语言:javascript
复制
message Person {
  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

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

  string name = 1;
  int32 id = 2;
  string email = 3;
  repeated PhoneNumber phones = 4;
}
一对多关联

使用 map 类型可以定义一对多关联:

代码语言:javascript
复制
message Person {
  string name = 1;
  int32 id = 2;
  string email = 3;
  map<string, string> attributes = 4;
}

Protobuf 与 gRPC

Protobuf 经常与 gRPC 一起使用,gRPC 是一个高性能、开源和通用的 RPC 框架,由 Google 开发。它使用 HTTP/2 作为传输协议,并使用 Protobuf 作为接口定义语言。

定义 gRPC 服务

.proto 文件中定义 gRPC 服务:

代码语言:javascript
复制
syntax = "proto3";

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}
生成服务代码

使用 protoc 生成服务代码:

代码语言:javascript
复制
protoc --java_out=. --grpc-java_out=. helloworld.proto
实现服务

以 Java 为例,实现 Greeter 服务:

代码语言:javascript
复制
public class GreeterImpl extends GreeterGrpc.GreeterImplBase {
  @Override
  public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
    HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
    responseObserver.onNext(reply);
    responseObserver.onCompleted();
  }
}

Protobuf 的最佳实践

  1. 合理定义字段编号:字段编号一旦定义,尽量不要修改,以保持向后兼容。
  2. 使用默认值:Protobuf 的每个字段都有默认值,如字符串的默认值是空字符串,数值的默认值是零等。
  3. 避免重复字段编号:不同消息类型中的字段编号是独立的,但同一消息类型中的字段编号必须唯一。
  4. 利用 reserved 关键字:如果需要废弃某个字段编号或字段名称,可以使用 reserved 关键字: proto复制代码message Person { reserved 4, 5; reserved "old_field"; string name = 1; int32 id = 2; string email = 3; }

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 为什么选择 Protobuf
  • 安装与环境配置
    • 在 macOS 上
      • 在 Ubuntu 上
        • 在 Windows 上
        • 定义 Protocol Buffer 消息
        • 编译 .proto 文件
        • 使用生成的代码
          • 序列化
            • 反序列化
            • Protobuf 高级特性
              • 可选和重复字段
                • 嵌套消息
                  • 枚举类型
                    • 一对多关联
                    • Protobuf 与 gRPC
                      • 定义 gRPC 服务
                        • 生成服务代码
                          • 实现服务
                          • Protobuf 的最佳实践
                          领券
                          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档