如何版本化你的API?--转

原文地址:http://www.infoq.com/cn/news/2017/09/How-versioning-API前端

如何版本化API须要考虑各类实际业务场景,可是一个完备的API应该是:nginx

  • 和客户端交互的约定。API须要确保稳定性,预先定义各类可能返回状态,包括各类异常。客户端无需考虑约定以外的状况。
  • 向下兼容。在API没有变化的时候,API实现的更新和升级,都应该确保原有客户端请求不出现问题。
  • RESTful。API设计应该可以遵守RESTful风格,经过URI来表示资源,经过HTTP GET、POST、PUT、DELETE等方法表示操做行为。

为了知足上述约定,版本化API不失为一种保持兼容性的好方法。版本化API的一般方式有:json

URI中设置版本后端

这种方式一般在URI中增长一段用于标识版本,例如/v1/v2等。例如:api

curl https://example.com/api/v2/lists/3  

这种方式的优点在于版本信息很容易明显的看出来,能够经过浏览器直接访问。浏览器

HTTP头中设置版本app

这种方式的版本信息会放在HTTP的请求头中,一般会利用Accept字段,或者自定义一个字段。例如:curl

curl https://example.com/api/lists/3 \  
-H 'Accept: application/vnd.example.v2+json'

这种方式的好处是当版本升级时,URI保持不变,而且仅用于表示资源定位。url

没有版本设计

版本化的目的是为了标识API的变化,若是API不会变化,或者每次都会从新扩展新的API,这种状况下,就能够标识版本信息。例如:

curl https://example.com/api/lists/3

一种折中方案

前面提到了三种版本化API的方式,一般状况下须要针对本身业务的特殊性来挑选其中的一种方式。可是,在实际应用场景中,状况会更加复杂,API的升级一般有两种状况:

  1. 大版本更新,例如字段类型变动、数据对象变动等。这种状况下没法知足对客户端的向下兼容,所以须要修改版本号。
  2. 小版本更新,例如增长可选参数、增长返回字段等。这种状况对于新客户端能够增长功能,对于老客户端仍然能够保持原有功能,能够不修改版本号。

所以,本文提出的折中方案是基于URI中的大版本号和HTTP头中的小版本号整合的方式。下面经过一个简单的示例来解释。

用户管理平台

一个经常使用的用户管理平台,提供如下API,经过用户ID获取用户信息:

curl https://example.com/api/v1/user/1
...
{
  "id": 1,
  "name": "test",
  "email": "test@example.com"
}

考虑如下两种变更状况:一种是用户id从数字变成了字符串,另外一种是新增一个用户头像的值。

前者修改由于数据类型的变化,会致使客户端解析出现问题。所以这样的修改已经破坏了向下兼容性,此时就须要修改API的版本号。例如:

curl https://example.com/api/v2/user/1
...
{
  "id": "1",
  "name": "test",
  "email": "test@example.com"
}

第二种状况,对于旧客户端来讲,只是增长了不使用的字段,一般的JSON格式解析库均可以忽略这些不使用的字段。对于新客户端则能够读取新的字段。例如:

curl https://example.com/api/v2/user/1
...
{
  "id": "1",
  "name": "test",
  "email": "test@example.com",
  "avatar": "http://example.com/1.jpg"
}

这种状况下,基本能够作到向下兼容,所以能够算是“小版本升级”。针对小版本升级,能够将小版本号放到HTTP头中。例如:

curl https://example.com/api/v2/user/1 \
    -H 'API-VERSION: 20170801'
...
{
  "id": "1",
  "name": "test",
  "email": "test@example.com",
  "avatar": "http://example.com/1.jpg"
}

后端路由

因为混合版本化的方式同时涉及到URI和HTTP头字段,前端代理(例如HAProxy、nginx)能够经过这些特定版本号字段将请求代理到对应的后端应用。

例如,前端使用HAProxy进行多版本分发,能够针对URI和HTTP头定制acl,而后再对这些acl进行组合,设置不一样的backend。

acl is_v1 path_beg /api/v1
acl is_v2 path_beg /api/v2
acl is_version_1 hdr(API-VERSION) 20170801
acl is_version_2 hdr(API-VERSION) 20170701
use_backend old_server if is_v1 is_version_1
use_backend new_server if is_v2 is_version_2
backend old_server
...
backend new_server
...

这样能够将API版本化规则应用到不一样的后端,以保证向下兼容性。

总结

基于本文版本化API规则,将“大版本”应用在URI上,将“小版本”应用在HTTP头字段上。一般来讲,若是API升级以后破坏了向下兼容性,就应该升级“大版本”号;若是API升级能够向下兼容,能够升级“小版本”号。

版本化API有不少不一样的设计方式,本文仅是其中一种。实际应用时,仍是要根据业务场景进行选择,包括API版本升级频率,API稳定性等。经过HAProxy、nginx等代理服务,能够在确保向下兼容的状况下,由业务方决定老版本API的保留时间。

相关文章
相关标签/搜索