服务接口很难不发生改变,那我们该如何应对这种改变呢?下面是一些应对策略:

1 容错性读取

最好的策略就是不对接口进行破坏性修改。但这几乎是不可能的。客户端应该应用 Postel 法则 ( 也叫作鲁棒性原则 ) 灵活地应对服务端接口所发生的变化。鲁棒是 Robust 的音译,也就是健壮和强壮的意思。指的是系统在异常和危险情况下的生存能力。比如说,计算机软件在输入错误 、 磁盘故障 、 网络过载或有意攻击情况下,能否不死机 、 不崩溃,就是该软件的鲁棒性。客户端应该宽进严出,即对自己所发送的内容要严格,但对所接收的内容则要宽容。

假设一个邮件服务:客户端传送客户 ID 给服务端,服务端返回该客户的基本信息,响应报文如下:

<customer>
    <firstname>Sam</firstname>
    <lastname>Newman</lastname>
    <email>sam@magpiebraincom</email>
    <telephoneNumber>555- 1234 -5678</telephoneNumber>
</customer>

后来,服务端觉得这是邮件服务,因此客户的电话号码没有必要发送;而且还想把客户的相关姓名整合在一个新的节点中。重构后的响应报文如下:

<customer>
    <naming>
        <firstname>Sam</firstname>
        <lastname>Newman</lastname>
    </naming>
    <email>sam@magpiebraincom</email>
</customer>

如果客户端采用绑定技术直接绑定字段,就会发生错误,不够健壮。这里,客户端可以采用 Xpath 技术来获取想要的数据,实现是 MartinFowler 所说的容错性读取。

XPath 是 XML 路径语言( XML PathLanguage),它是一种用来确定 XML 文档中某部分位置的语言。


在请求 / 响应的应用场景, 容错性读取原则可以实现服务端改变时,最大限度地减少客户端的修改 。

2 提早发现

服务端更新了服务,客户端应该完整运行一遍之前所写的测试用例,尽早发现问题。

3 版本语义化

版本语义化指的是,客户端能够通过查看服务的版本号,就可以知道是否能够与之进行集成。版本格式为:主版本号.次版本号.修订号,版本号递增规则如下:

  1. 主版本号:修改后的 API,无法向下兼容。
  2. 次版本号:新增了功能,并可向下兼容。
  3. 修订号:修正了问题,并可向下兼容。
    先行版本号及版本编译元数据可以加到“主版本号.次版本号.修订号”的后面,作为延伸。

向下兼容(Downward Compatibility),又称作向后兼容(Backward Compatibility)。一个程序或者类库更新到较新版本之后,用旧的版本程序创建的文档或系统仍能被正常操作或使用,或在旧版本的类库的基础上开发的程序仍能正常编译运行的情况。也就是说,旧的程序仍然可在其上编译与运行。

4 接口并存

服务端对一个原接口进行了脱胎换骨的重新设计之后,但并没有修改原接口,而是实现了新接口,并且让新老接口同时存在。

通过这种方式,就可以我们尽快发布新版本的微服务。因为新老接口同时存在,客户端也有时间迁移过渡到新接口。一旦所有客户端不再使用老接口,就可以移除掉这个接口。

这其实是一种扩展 / 收缩模型,这可以让客户端从旧接口平滑过渡到新接口。首先扩展服务能力,可同时支持对新旧两种接口。等所有客户端都过渡到了新接口之后,再通过收缩服务能力,从 API 中去除旧接口。

对于使用 HTTP 作为交互模型的系统来说,我们可以在请求中添加版本信息,也可以将其添加在 URI 中,比如vl/customer/v2/customer/

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐