建模 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;
}
使用 Any
比 string payload
有以下优点:
- 鼓励使用协议缓冲区来定义动态负载内容
- Protocol Buffer 库中针对每种语言的工具,用于将 Protocol Buffer 消息打包和解包为
Any
类型
有关 Any
的更多信息,请参阅:
我想为双向流式传输消息建模。在这两个方向上,我都可以期待不同类型的消息,我不确定更好的做法是什么。目前的两个想法:
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;
}
使用 Any
比 string payload
有以下优点:
- 鼓励使用协议缓冲区来定义动态负载内容
- Protocol Buffer 库中针对每种语言的工具,用于将 Protocol Buffer 消息打包和解包为
Any
类型
有关 Any
的更多信息,请参阅: