我知道 protobuf/thrift 需要唯一的数字字段标签来提供版本兼容性。它们通过以这种方式序列化消息(某种)来提供版本兼容性:
<tag1> <value1> ... <tagN> <valueN>
反序列化时,它们获取标记值,查找消息模式,并知道将值填充到哪个字段。这样,只要我们添加不同标签值的新字段,消息就会兼容。
但我不认为这是一个很好的设计:
标签值必须在消息中进行编码。这有一些开销。
例如。当客户端多次调用远程服务器上的 RPC 方法时,每个请求/响应中的标记值都是相同的。最好只发送
<tag1> <value1> ... <tagN> <valueN>
一次,然后只发送<value1> ... <valueN>
。当改变一个字段的类型时,我们也需要改变标签值。忘记这样做会导致错误。
开发人员必须确保标签值是唯一的。通常人们会跟踪上次使用的标签 ID,并在添加新字段时增加它。但是当两个人在不同的分支中添加字段并进行合并时,很难解决冲突。
我认为更好的设计可能是:
为每种消息类型创建一个紧凑的模式,如下所示:
<field_name_1> <field_type_1> ... <field_name_N> <field_type_N>
(按字段名排序)
要解决问题 1,请在执行任何操作之前交换消息模式。对于 RPC 示例,客户端将在发送第一个 RPC 之前发送其消息模式,然后在接下来的 RPC 中,它只发送<value_1> ... <value_N>
. 当请求到达时,服务器将具有消息模式,并且知道如何反序列化它。
为了解决问题 2,当字段类型更改时,紧凑消息模式也将更改。程序将能够找出新旧模式不匹配,并报告错误。
为了解决问题 3,开发人员不再需要注意分配唯一的标签值。他们仍然需要注意分配唯一的字段名称,但这应该更容易,并且不太可能导致合并冲突。
这可能是一个可用的设计吗?它会出现什么问题?