Protobuf简介

10

title: Protobuf语法
description:
published: true
date: 2024-11-09T07:40:56.593Z
tags:
editor: markdown

dateCreated: 2024-11-09T07:40:56.593Z

Proto3 是 Protocol Buffers 的第三版,是一种由 Google 开发的数据序列化格式。它被设计用来高效地描述结构化数据并提供跨语言的数据交换。Proto3 相较于之前版本 (proto2) 做了一些简化和改进:

  1. 去掉了可选和必需字段
  2. proto3 中所有字段都默认是可选的,不再需要 optionalrequired 关键字。
  3. 默认值
  4. proto3 中所有标量字段都有默认值,例如 int32 的默认值为 0string 的默认值为空字符串。
  5. 移除了一些 proto2 特性
  6. proto3 去掉了默认值的显式设置、扩展、以及自定义选项等特性。

下面是 proto3 的语法和数据类型的详细介绍:

基本语法

1. 语法声明

必须在文件的开头声明使用 proto3 语法。

syntax = "proto3";

命名空间

option csharp_namespace = "GrpcServiceDemo";

2. 包声明

定义消息和服务所属的命名空间。

package example;

3. 导入其他 proto 文件

导入其他 proto 文件中的定义,可以是标准库中的文件或用户定义的文件。

import "google/protobuf/timestamp.proto";
import "google/protobuf/empty.proto";

4. 消息定义

消息类型用来定义数据结构,包含字段及其类型。

message SimpleMessage {
  int32 id = 1;
  string content = 2;
}

数据类型

Proto3 支持多种数据类型,主要包括以下几类:

1. 标量类型

| 类型 | 说明 |
|———-|——————————–|
| double | 双精度浮点数 |
| float | 单精度浮点数 |
| int32 | 32位有符号整数 |
| int64 | 64位有符号整数 |
| uint32 | 32位无符号整数 |
| uint64 | 64位无符号整数 |
| sint32 | 32位有符号整数(使用压缩编码) |
| sint64 | 64位有符号整数(使用压缩编码) |
| fixed32| 32位定长有符号整数 |
| fixed64| 64位定长有符号整数 |
| sfixed32| 32位定长有符号整数 |
| sfixed64| 64位定长有符号整数 |
| bool | 布尔值 |
| string | 字符串 |
| bytes | 字节序列 |

2. 枚举类型

枚举类型用来定义一组命名常量。

enum EnumExample {
  UNKNOWN = 0;
  STARTED = 1;
  RUNNING = 2;
  FINISHED = 3;
}

3. 嵌套消息

message OuterMessage {
  message InnerMessage {
    int32 id = 1;
  }
  InnerMessage inner = 1;
}

消息类型可以嵌套定义。

4. 列表

使用 repeated 关键字定义列表字段。

message ListMessage {
  repeated int32 values = 1;
}

5.字典

使用 map<key_type, value_type> 定义字典。

message DictionaryMessage {
  map<string, string> dictionary = 1;
}

6. 特殊类型

  • google.protobuf.Timestamp: 用来表示时间戳。
  • google.protobuf.Duration: 用来表示时间段。
  • google.protobuf.Empty: 空消息类型,通常用于无需请求或响应消息的场景。

7.字段标签

每个字段都有一个唯一的标签号,标签号在一个消息中必须唯一,并且应在1到2^29-1之间。以下是一些示例:

message Example {
  int32 id = 1;
  string name = 2;
  repeated string tags = 3;
}

服务定义

服务用来定义 RPC 接口,可以包含一个或多个 RPC 方法。

service ExampleService {
  rpc GetExample (ExampleRequest) returns (ExampleResponse);
}

三种流模式的使用场景

  1. 客户端流

  2. 用于客户端需要连续发送多个请求,然后服务器根据所有请求消息返回一个响应的场景。

  3. 示例:文件上传、数据批量处理。

  4. 服务端流

  5. 用于客户端发送一个请求,然后服务器连续返回多个响应消息的场景。

  6. 示例:实时数据推送、长时间运行的查询。

  7. 双向流

  8. 用于客户端和服务器需要同时发送和接收消息的复杂交互场景。

  9. 示例:实时聊天、视频会议。

通过这些示例,可以更好地理解如何在 proto 文件中定义和使用 gRPC 的三种流模式。

客户端流(Client Streaming)

客户端流模式允许客户端发送一系列请求消息到服务器,服务器在收到所有请求消息后才返回一个响应消息。下面是一个客户端流模式的示例:

syntax = "proto3";

package example;

message RequestMessage {
  int32 id = 1;
  string content = 2;
}

message ResponseMessage {
  string result = 1;
}

service ExampleService {
  // 客户端流模式
  rpc ClientStreaming (stream RequestMessage) returns (ResponseMessage);
}

在这个例子中,ClientStreaming 方法接收一个RequestMessage类型的流,并返回一个ResponseMessage类型的单一响应。

服务端流(Server Streaming)

服务端流模式允许服务器发送一系列响应消息到客户端,客户端在收到所有响应消息后才处理。下面是一个服务端流模式的示例:

syntax = "proto3";

package example;

message RequestMessage {
  int32 id = 1;
  string content = 2;
}

message ResponseMessage {
  string result = 1;
}

service ExampleService {
  // 服务端流模式
  rpc ServerStreaming (RequestMessage) returns (stream ResponseMessage);
}

在这个例子中,ServerStreaming 方法接收一个RequestMessage类型的单一请求,并返回一个ResponseMessage类型的流。

双向流(Bidirectional Streaming)

双向流模式允许客户端和服务器之间进行双向的消息流,每一方都可以独立地发送和接收消息。下面是一个双向流模式的示例:

syntax = "proto3";

package example;

message RequestMessage {
  int32 id = 1;
  string content = 2;
}

message ResponseMessage {
  string result = 1;
}

service ExampleService {
  // 双向流模式
  rpc BidirectionalStreaming (stream RequestMessage) returns (stream ResponseMessage);
}

在这个例子中,BidirectionalStreaming 方法接收一个RequestMessage类型的流,并返回一个ResponseMessage类型的流。

代码示例

下面是一个完整的 proto3 文件示例,涵盖了上述各种数据类型和语法特性:

syntax = "proto3";

package example;

import "google/protobuf/timestamp.proto";
import "google/protobuf/empty.proto";

enum Status {
  UNKNOWN = 0;
  ACTIVE = 1;
  INACTIVE = 2;
}

message User {
  int32 id = 1;
  string name = 2;
  bool is_active = 3;
  Status status = 4;
  google.protobuf.Timestamp last_login = 5;
  map<string, string> metadata = 6;
}

message UserList {
  repeated User users = 1;
}

service UserService {
  rpc GetUser (User) returns (User);
  rpc ListUsers (google.protobuf.Empty) returns (UserList);
  rpc CreateUser (User) returns (User);
}

这个文件定义了一个简单的用户管理系统,包括用户的基本信息、状态、最后登录时间以及一些元数据,并定义了用户服务的三个方法:获取用户信息、列出所有用户以及创建新用户。