如何版本化你的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的保留時間。

相關文章
相關標籤/搜索