可以从 protobuf/thrift 消息中删除字段标签吗?
Can field tags be dropped from protobuf/thrift messages?
我知道 protobuf/thrift 需要唯一的数字字段标签来提供版本兼容性。它们通过以这种方式(某种程度上)序列化消息来提供版本兼容性:
<tag1> <value1> ... <tagN> <valueN>
在反序列化时,他们获取标签值,查找消息模式,并知道将值填充到哪个字段。这样,只要我们添加不同标签值的新字段,消息就会兼容。
但我认为这不是一个很好的设计:
标签值必须在消息中进行编码。这有一些开销。
例如。当客户端多次调用远程服务器上的RPC方法时,每次request/response中的tag值都是相同的。最好只发送一次<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,开发人员不再需要负责分配唯一标记值。他们仍然需要注意分配唯一的字段名称,但这应该更容易,并且不太可能导致合并冲突。
这可能是一个可用的设计吗?又会有什么问题呢?
我相信 Apache Avro 的工作方式与您描述的一样,所以也许您应该尝试一下。
但是,我认为前期模式协商给协议增加了大量的复杂性,这超过了任何好处。在简单的情况下,这似乎很容易,但在大型系统中,您有代理(不知道它们在代理什么)、专用存储服务器、由从具有不同协议版本的多个发件人接收的片段组成的消息等,跟踪架构版本的复杂性成为一个巨大的负担。
我知道 protobuf/thrift 需要唯一的数字字段标签来提供版本兼容性。它们通过以这种方式(某种程度上)序列化消息来提供版本兼容性:
<tag1> <value1> ... <tagN> <valueN>
在反序列化时,他们获取标签值,查找消息模式,并知道将值填充到哪个字段。这样,只要我们添加不同标签值的新字段,消息就会兼容。
但我认为这不是一个很好的设计:
标签值必须在消息中进行编码。这有一些开销。
例如。当客户端多次调用远程服务器上的RPC方法时,每次request/response中的tag值都是相同的。最好只发送一次
<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,开发人员不再需要负责分配唯一标记值。他们仍然需要注意分配唯一的字段名称,但这应该更容易,并且不太可能导致合并冲突。
这可能是一个可用的设计吗?又会有什么问题呢?
我相信 Apache Avro 的工作方式与您描述的一样,所以也许您应该尝试一下。
但是,我认为前期模式协商给协议增加了大量的复杂性,这超过了任何好处。在简单的情况下,这似乎很容易,但在大型系统中,您有代理(不知道它们在代理什么)、专用存储服务器、由从具有不同协议版本的多个发件人接收的片段组成的消息等,跟踪架构版本的复杂性成为一个巨大的负担。