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

Ban*_*ore 5 java thrift microservices

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

假设下面是摘要对象的节约合同,并且有一个API可使用传递的摘要对象来获取和更新摘要。

版本-1.0

struct Summary {
    1: required string summaryId,
    2: required i32 summaryCost
}

Summary getSummary(1: string summaryId);

void updateSummary(1: Summary summary);
Run Code Online (Sandbox Code Playgroud)

现在,假设有5个服务正在使用此1.0摘要协议。
在下一发行版中,我们添加另一个对象,该对象称为summaryvalue列表

所以新合同看起来像

版本-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);
Run Code Online (Sandbox Code Playgroud)
  1. 因此,当填充以下列表时,我们将保存值summaryValuesaganist 的列表summaryId
  2. 当客户端发送此列表时,null我们将删除为该“ summaryId”保存的现有值。

现在的问题发生时正在使用其他服务较旧的节俭合同(版本1.0版)尝试致电getSummary和updateSummary。
旧客户通过调用updateSummary的意图是为设置另一个值summaryCost。但是,由于此客户端不包含对象,summaryValues因此它将带有summaryValuesnull 的Summary对象发送给Server。

这导致的服务器上删除的所有现有值在summaryValuessummaryId

有办法省事吗?isSet()方法在这里不起作用,因为它们尝试执行简单的null检查。
每次发布对现有对象进行修改的新客户端时,即使更改与其他服务器无关,我们都必须强制升级其他服务器的客户端版本。

Sha*_*ick 4

在您的方法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
}
Run Code Online (Sandbox Code Playgroud)

这样,如果apiVersion未设置,您就知道请求来自旧客户端,对于未来版本,您将知道客户端版本并可以做出相应反应。


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

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