我们目前正在使用节俭来开发我们的微服务。 当我最近遇到这个问题时。
假设下面是摘要对象的thrift合约,并且有一个API使用传递的摘要对象获取和更新摘要。
版本 - 1.0
struct Summary {
1: required string summaryId,
2: required i32 summaryCost
}
Summary getSummary(1: string summaryId);
void updateSummary(1: Summary summary);
现在假设有5个服务正在使用此 1.0 摘要合同 在下一个版本中,我们添加另一个名为 summaryvalues列表的对象。
所以新合同看起来像是
版本 - 2.0
struct Summary {
1: required string summaryId,
2: required i32 summaryCost,
3: optional list<i32> summaryValues
}
Summary getSummary(1: string summaryId);
void updateSummary(1: Summary summary);
summaryValues
的值列表summaryId
。null
时,我们会删除为该'summaryId`保存的现有值。现在,当使用 OLDER 版本的thrift合约(版本1.0 )的其他服务尝试调用getSummary和updateSummary时,会出现问题 。
通过调用updateSummary,老客户的意图是为summaryCost
设置另一个值。但是,由于此客户端不包含对象summaryValues
,因此它将带有summaryValues
的Summary对象作为null发送给服务器。
这导致服务器删除了summaryValues
的{{1}}的所有现有值。
有没有办法在节俭中处理这个问题? isSet()方法在这里不起作用,因为它们尝试执行简单的空检查 每次我们通过修改现有对象来发布更新的客户端时,我们都必须强制升级其他服务器的客户端版本,即使更改与它们无关。
答案 0 :(得分:3)
在version 2.0
updateSummary()
方法的合同已更改(即,现在它允许保存和删除汇总值):
选项1:
而不是改变其行为,创建一个新方法(即updateSummaryV2()
)并开始在最新版本的客户端中使用它,同时弃用旧方法。
这样,旧版本的客户端仍然使用普通updateSummary()
而不会与新方法的合同和假设发生冲突。
选项2: 添加包含api版本的可选字段,并将默认值设置为最新的API版本:
struct Summary {
1: required string summaryId,
2: required i32 summaryCost,
3: optional list<i32> summaryValues
4: optional i32 apiVersion = 2
}
这样,如果未设置apiVersion
,则您知道该请求来自旧客户端,对于将来的版本,您将了解客户端版本并可以做出相应的反应。
或者,您只能在提供空列表时删除记录,如果未设置列表则不执行任何操作,以遵守以前的方法合同。
作为旁注:即使不考虑交叉兼容性问题,依赖于隐含的某些操作(此处,缺少列表)也可能存在风险。当此类操作依赖于显式标志时,它通常更安全(并且更易于使用和维护)。