如何将多个 protobufs 放在一条线上

how to put multiple protobufs on a wire

我们有一个发送 protobuf 的通信通道。为了能够发送不止一种类型的protobuf,我们进行双序列化:

message Coprolite {
    enum Bezoar {
        KBezoarUndef = 0;
        KBezoarFriedEggs = 1;
        KBezoarHam = 2;
    }
    Bezoar payload_type = 1;
    bytes payload = 2;
}

如果我有一个 FriedEggs protobuf,我将其序列化,将其分配给 Coprolite 的有效负载,将 payload_type 设置为 KBezoarFriedEggs,序列化 Coprolite,然后将其发送。

收到后,我反序列化,检查我有什么,然后反序列化。

这适用于我们所有的平台。但是,我还没有找到其他人以这种方式(实际上也没有任何其他方式)这样做的例子。所以这表明我应该征求意见。有没有更好的策略或理由让我对此保持警惕?

如果您想避免设置 payload_type,您可以使用 oneof。 Oneof通过在前面添加标签号来隐式序列化payload类型。就像序列化的任何其他字段一样。所以你必须少写一些管理代码。

但是,与使用其中之一相比,您的方法有一个优势。深入了解您的编程语言以及如何在您的平台和 protobuf 库中实现 oneof 和字节数组。作为联合实现的 oneof 可能会分配最大嵌套消息大小的内存。因此,根据您的情况,动态分配字节数组可能会在您发送大量小消息且有时发送大消息时使用更少的内存。

这里有两种常见的方法;最简单的(尤其是当类型可以提前预测时)通常是 oneof:

message Coprolite {
    oneof payload_type {
         FriedEggs eggs = 1;
         Ham ham = 2;
    }
}

这就像一个可区分的联合,您可以在其中检查嵌入类型。

在一些小众场景下,你可能更喜欢使用Any