2

我正在运行一个需要

  • 不同编程语言(主要是java、c++)之间的相互通信。
  • 可以序列化/反序列化为二进制格式和 json 格式。
  • IDL 为不同语言生成类代码

Thrift 完全符合这些标准,尽管我们不需要它的 RPC 函数。我们将通过 MQ 发送/接收序列化的节俭数据。序列化对象非常简单。但是,当涉及到反序列化时,我们不能这样做:

byte[] data = recv();
Object object = TDeserializer.deserialize(data);
if (object instanceof TypeA) {
    TypeA a = (TypeA) object;
} else if (object instanceof TypeB) {
    TypeB b = (TypeB) object;
}

看来我们必须准确地告诉 thrift 它需要反序列化为哪个结构,例如:

byte[] data = recv();
TypeA a;
TDeserializer.deserialize(a, data);

只是想知道是否有一种方法可以在不知道其确切类型的情况下将原始数据反序列化为节俭对象。

谢谢!!

4

1 回答 1

12

Thrift 序列化消息本身不包含类型信息,因此反序列化器必须知道消息数据类型。但是,可以将所有必要的数据类型包装到联合中。

节俭代码:

union Message {
    1: TypeA a;
    2: TypeB b;
}

反序列化代码:

byte[] data = recv();
Message msg;
TDeserializer.deserialize(msg, data);
<find out message type with msg.getSetField()>

如果您需要添加新的消息类型,只需在 union 中添加另一个字段。如果您不接触旧的字段 ID,您将保持向后兼容性:

union Message {
    1: TypeA a;
    2: TypeB b;
    3: TypeC c; <-- OK
}

您将能够接收来自旧生产者的消息(他们永远不会发送TypeC消息)并向旧消费者发送TypeA/消息。TypeB如果您向TypeC不知道字段#3 的消费者发送消息,它将获得异常。

这种方法的最大优点是类型信息非常紧凑。如果使用TCompactProtocol,在大多数情况下,类型 info 将只占用 1 个额外字节(如果字段 IDMessage小于 127)。

请注意,如果您更改字段 ID,您将失去向后兼容性。例如:

union Message {
    1: TypeA a;
    2: TypeC c; <-- Wrong
    3: TypeB b; <-- Wrong
    4: TypeD d; <-- OK
}
于 2013-06-04T18:16:35.013 回答