据我所知,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>
(根据field_name排序)
要解决问题1,请在执行任何操作之前交换消息架构。对于RPC示例,客户端将在发送第一个RPC之前发送其消息模式,然后在以下RPC中,它仅发送<value_1> ... <value_N>
。当请求到达时,服务器将具有消息模式,并且知道如何反序列化它。
要解决问题2,当更改字段类型时,也会更改压缩消息架构。程序将能够找出旧的和新的架构不匹配,并报告错误。
要解决问题3,开发人员不再需要处理分配唯一标记值。他们仍然需要注意分配唯一的字段名称,但这应该更容易,并且不太可能导致合并冲突。
这可能是一个有用的设计吗?那会有什么问题呢?
答案 0 :(得分:2)
我相信Apache Avro就像你描述的那样工作,所以也许你应该尝试一下。
但是,我认为前期架构协商会给协议带来大量复杂性,这超过了任何好处。在简单的情况下看起来很简单,但是在大型系统中你有代理(不知道他们代理什么),专用存储服务器,从多个发件人收到的消息组成的消息对于不同的协议版本等,跟踪模式版本的复杂性成为一个巨大的负担。