天天看点

API版本管理

微服务的API是服务端和客户端之间的契约。我们只能在不破坏API契约的前提下独立地改进微服务,所以契约很重要。如果改变了契约,就会影响到客户端应用或API 网关。

API的定义依赖于所用协议。例如使用(诸如AMQP这类协议)消息时,API由消息类型组成。如果使用HTTP和REST风格的服务,API则由URL和请求以及JSON格式的响应组成。

然而,即便初始版本的契约已经考虑周全了,随着时间发展,服务的API也可能需要改变。如果发生了变化,尤其是被多个客户端应用调用的公共API,通常无法强制所有客户端升级到新的API契约。通常这需要增量部署服务的新版本,同时也要让老版本和新版本服务契约同时运行。因此,服务的版本策略很重要。

如果API的改动较小,例如添加了属性或参数,使用旧版API的客户端应该能切换过来,和新版服务协同工作。我们可以为必需的属性提供默认值,客户端将会忽略任何额外的属性。

但有时我们需要对服务API进行不兼容的大版本更新。因为不能强制客户端应用或服务立刻升级到新版,服务端必须支持老版本继续运行一段时间。如果使用基于HTTP的机制(如REST),一种方式是把API的版本号嵌入到URL或HTTP头部。然后可以决定是在一个服务里同时实现两个版本的API,或是部署不同的服务来各自处理一个版本的API。此时一种较好的方法是采用中介者模式(如MediatR库)将不同版本的实现用不同的处理器来处理。

最后,如果使用REST架构,Hypermedia是用来进行服务版本化和改进的最佳选择。

查询字符串版本控制

不是提供多个 URI,而是可以通过在追加到 HTTP 请求后面的查询字符串中使用参数来指定资源的版本,例如 

https://adventure-works.com/customers/3?version=2

。 如果 version 参数被较旧的客户端应用程序省略,则应默认为有意义的值(例如 1)。

无版本控制

这是最简单的方法,它对于一些内部 API 来说可能是可以接受的。 重大更改可以表示为新资源或新链接。 向现有资源添加内容可能不会显示重大更改,因为不应查看此内容的客户端应用程序将忽略它。

例如,向 URI 

https://adventure-works.com/customers/3

 发出请求应返回包含客户端应用程序所需的 

id

name

 和 

address

 字段的单个客户的详细信息:

URI 版本管理

每次修改 Web API 或更改资源的架构时,向每个资源的 URI 添加版本号。 以前存在的 URI 应像以前一样继续运行,并返回符合原始架构的资源。

标头版本控制

不是追加版本号作为查询字符串参数,而是可以实现指示资源的版本的自定义标头。 此方法需要客户端应用程序将相应标头添加到所有请求,虽然如果省略了版本标头,处理客户端请求的代码可以使用默认值(版本 1)。 下面的示例使用了名为 Custom-Header 的自定义标头。 此标头的值指示 Web API 的版本。

GET https://adventure-works.com/customers/3 HTTP/1.1

Custom-Header: api-version=1

GET https://adventure-works.com/customers/3 HTTP/1.1

Custom-Header: api-version=2

媒体类型版本控制

如本指南前面所述,当客户端应用程序向 Web 服务器发送 HTTP GET 请求时,它应使用 Accept 标头规定它可以处理的内容的格式。 通常,Accept 标头的用途是允许客户端应用程序指定响应的正文应是 XML、JSON 还是客户端可以分析的其他某种常见格式。 但是,可以定义包括以下信息的自定义媒体类型:该信息使客户端应用程序可以指示它所需的资源版本。 下面的示例演示了将 Accept 标头指定为值 application/vnd.adventure-works.v1+json 的请求。 vnd.adventure-works.v1 元素向 Web 服务器指示它应返回资源的版本 1,而 json 元素则指定响应正文的格式应为 JSON:

HTTP复制

GET https://adventure-works.com/customers/3 HTTP/1.1
Accept: application/vnd.adventure-works.v1+json
           

继续阅读