0

我知道 protobuf/thrift 需要唯一的数字字段标签来提供版本兼容性。它们通过以这种方式序列化消息(某种)来提供版本兼容性:

<tag1> <value1> ... <tagN> <valueN>

反序列化时,它们获取标记值,查找消息模式,并知道将值填充到哪个字段。这样,只要我们添加不同标签值的新字段,消息就会兼容。

但我不认为这是一个很好的设计:

  1. 标签值必须在消息中进行编码。这有一些开销。

    例如。当客户端多次调用远程服务器上的 RPC 方法时,每个请求/响应中的标记值都是相同的。最好只发送<tag1> <value1> ... <tagN> <valueN>一次,然后只发送<value1> ... <valueN>

  2. 当改变一个字段的类型时,我们也需要改变标签值。忘记这样做会导致错误。

  3. 开发人员必须确保标签值是唯一的。通常人们会跟踪上次使用的标签 ID,并在添加新字段时增加它。但是当两个人在不同的分支中添加字段并进行合并时,很难解决冲突。

我认为更好的设计可能是:

为每种消息类型创建一个紧凑的模式,如下所示:

<field_name_1> <field_type_1> ... <field_name_N> <field_type_N>(按字段名排序)

要解决问题 1,请在执行任何操作之前交换消息模式。对于 RPC 示例,客户端将在发送第一个 RPC 之前发送其消息模式,然后在接下来的 RPC 中,它只发送<value_1> ... <value_N>. 当请求到达时,服务器将具有消息模式,并且知道如何反序列化它。

为了解决问题 2,当字段类型更改时,紧凑消息模式也将更改。程序将能够找出新旧模式不匹配,并报告错误。

为了解决问题 3,开发人员不再需要注意分配唯一的标签值。他们仍然需要注意分配唯一的字段名称,但这应该更容易,并且不太可能导致合并冲突。

这可能是一个可用的设计吗?它会出现什么问题?

4

1 回答 1

2

我相信 Apache Avro 就像您描述的那样工作,所以也许您应该尝试一下。

然而,我认为前期的模式协商给协议增加了大量的复杂性,这超过了任何好处。在简单的情况下,这似乎很容易,但在一个大型系统中,您有代理(不知道它们在代理什么)、专用存储服务器、由从具有不同协议版本的多个发件人收到的片段组成的消息等,跟踪模​​式版本的复杂性成为一个巨大的负担。

于 2015-01-15T02:52:33.597 回答