如何确保节俭对象向后兼容?

时间:2016-08-22 20:31:30

标签: java thrift microservices

我们目前正在使用节俭来开发我们的微服务。 当我最近遇到这个问题时。

假设下面是摘要对象的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);
  1. 因此,当填充以下列表时,我们会保存值summaryValues的值列表summaryId
  2. 当客户端将此列表发送为null时,我们会删除为该'summaryId`保存的现有值。
  3. 现在,当使用 OLDER 版本的thrift合约(版本1.0 )的其他服务尝试调用getSummary和updateSummary时,会出现问题
    通过调用updateSummary,老客户的意图是为summaryCost设置另一个值。但是,由于此客户端不包含对象summaryValues,因此它将带有summaryValues的Summary对象作为null发送给服务器。

    这导致服务器删除了summaryValues的{​​{1}}的所有现有值。

    有没有办法在节俭中处理这个问题? isSet()方法在这里不起作用,因为它们尝试执行简单的空检查 每次我们通过修改现有对象来发布更新的客户端时,我们都必须强制升级其他服务器的客户端版本,即使更改与它们无关。

1 个答案:

答案 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,则您知道该请求来自旧客户端,对于将来的版本,您将了解客户端版本并可以做出相应的反应。

或者,您只能在提供空列表时删除记录,如果未设置列表则不执行任何操作,以遵守以前的方法合同。

作为旁注:即使不考虑交叉兼容性问题,依赖于隐含的某些操作(此处,缺少列表)也可能存在风险。当此类操作依赖于显式标志时,它通常更安全(并且更易于使用和维护)。