Xu *_*Yao 3 message-queue protocol-buffers
我想使用protobuf而不是Json在消息队列之间进行通信。
当只有一条原始消息时,我知道如何处理。
假设原始文件为:
//person.proto
syntax = "proto3";
option java_outer_classname = "PersonProto";
message Person {
int32 id = 2;
string name = 1;
string email = 3;
}
Run Code Online (Sandbox Code Playgroud)
现在,我可以使用以下方法处理它:
PersonProto.Person person = PersonProto.Person.newBuilder()
.setEmail("123@test.com")
.setId(1)
.setName("name-test")
.build();
byte[] bytes = person.toByteArray();
//Transfer from publisher to consumer between message queue.
//I can deserialise it, because i know the proto message is Person.
PersonProto.Person.parseFrom(bytes);
Run Code Online (Sandbox Code Playgroud)
但是,如果有多个原始消息怎么办?
假设还有另一个原始消息称为Address。
syntax = "proto3";
option java_outer_classname = "PersonProto";
message Person {
int32 id = 2;
string name = 1;
string email = 3;
}
message Address {
string address = 1;
}
Run Code Online (Sandbox Code Playgroud)
当使用者从消息队列接收字节数组时,如何知道它是哪个原始消息?以及如何反序列化字节数组?
Protobuf 3引入了Any的概念,可以以类似于@AdamCozzette解释的顶级消息模式的方式工作。
在写方,您将消息打包在Any中:
Person person = ...
Any any = Any.pack(person);
out.write(any.toByteArray());
Run Code Online (Sandbox Code Playgroud)
然后在读取侧读入Any并打开您感兴趣的类型:
Any any = Any.parseFrom(in);
if (any.is(Person.class)
{
Person person = any.unpack(Person.class);
...
}
else if (any.is(Address.class);
{
Address address = any.unpack(Address.class);
...
}
else
{
//Handle unknown message
}
Run Code Online (Sandbox Code Playgroud)
使用Any消除了对特殊消息类型(top-level-message)的需求,而且还消除了类型安全元素,因为您可能会收到使用方代码不知道如何处理的消息。
小智 5
协议缓冲区不是自描述的,所以一般来说,当你得到一个序列化的 protobuf 时,如果不知道预期的模式,就无法解释它的内容。
在您的情况下,我建议使用一个oneof字段。您可以为队列消息使用一个顶级消息类型,并让它包含一个oneof包含人员或地址的字段:
message TopLevelMessage {
oneof inner_message {
Person person = 1;
Address address = 2;
}
}
Run Code Online (Sandbox Code Playgroud)
消费代码然后需要一个像这样的 switch 语句来检索内部消息:
TopLevelMessage topLevelMessage = TopLevelMessage.parseFrom(...);
switch (topLevelMessage.getInnerMessageCase())
{
case PERSON:
Person person = topLevelMessage.getPerson();
...
break;
case ADDRESS:
Address address = topLevelMessage.getAddress();
...
break;
default:
...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4112 次 |
| 最近记录: |