建模 gRPC 消息的最佳方式

Best way to model gRPC messages

我想为双向流式传输消息建模。在这两个方向上,我都可以期待不同类型的消息,我不确定更好的做法是什么。目前的两个想法:

message MyMessage {
    MessageType type = 1;
    string payload = 2;
}

在这种情况下,我会有一个枚举来定义消息的类型,以及一个 JSON 有效载荷,它将被序列化和反序列化到客户端和服务器端的模型中。第二种方法是:

 message MyMessage {
    oneof type {
        A typeA = 1;
        B typeB = 2;
        C typeC = 3;
    }
}

在第二个示例中,定义了一个,以便只能设置一种消息类型。双方都必须在每种情况下进行切换(A、B、C 或 None)。

如果您提前知道所有可能的类型,使用 oneof 将是您所描述的方法。

使用协议缓冲区的主要原因是模式定义。通过模式定义,您可以获得类型、代码生成、安全模式演变、高效编码等。使用 oneof 方法,您将获得嵌套有效负载的这些好处。

我不建议使用 string payload,因为使用字符串作为实际负载会消除使用协议缓冲区的许多好处。此外,即使您不需要 switch 语句来反序列化有效负载,您也可能在某些时候需要 switch 语句来使用数据(除非您只是将数据转发到其他系统)。

备选方案

如果您事先不知道可能的类型,您可以使用 Any 类型将任意协议缓冲区消息嵌入到您的消息中。

import "google/protobuf/any.proto";

message MyMessage {
  google.protobuf.Any payload = 1;
}

Any 消息基本上是您的 string payload 方法,但使用字节而不是字符串。

message Any {
  string type_url = 1;
  bytes value = 2;
}

使用 Anystring payload 有以下优点:

  • 鼓励使用协议缓冲区来定义动态负载内容
  • Protocol Buffer 库中针对每种语言的工具,用于将 Protocol Buffer 消息打包和解包为 Any 类型

有关 Any 的更多信息,请参阅: