譯者注:本文主要描述了幾種API版本控制的方法。用戶能夠查詢原始的API,或者添加定製的頭文件來接收特定的版本。若是應用程序收到一個重大修訂,將URI修改成V2。在進行迭代改進時,將建立與更改日期相一致的端點,並容許用戶將日期信息附加。而後,能夠選擇保留舊版本的時間。並且在設計和版本化API時,您能夠應用許多不一樣的理念。如下爲譯文數據庫
API設計是一個「火辣熱門」的話題!關於API的最佳結構和版本的方法已經有不少優秀的文章介紹過了。在這篇文章中,咱們將會深刻研究不一樣的API設計之間有哪些衝突的地方,並在此基礎上提出咱們的中立觀點,而後展現咱們是怎樣使用FLY去驗證咱們的中立觀點的。json
API版本控制
雖然沒有一個統一的方式來設計API,可是有必要明確一下許多開發人員贊成的幾個關鍵想法。一個結構良好的Web API應該是…後端
1:與客戶端保持持續的協議。協議能夠保證一致性和穩定性;客戶端應該可使用API,而不用擔憂它會忽然中斷或消失。api
2:更改或升級後向後兼容。對新端點的舊查詢仍應產生預期的返回值。瀏覽器
3:RESTful(互聯網應用程序)。它應當能夠識別HTTP的相關動做 :GET,PUT,POST,PATCH,DELETE等。安全
爲了最好地實現這些理想的要求,在如何實現不一樣版本的API上就是仁者見仁,智者見智了。咱們來看看它們中的三個…app
URI版本控制框架
curl https://example.com/api/v2/lists/3
經過解除URI中的版本號,客戶端能夠訪問/v1/或/v2/API。它可讀,適應性強,可直接插入用戶瀏覽器。curl
Header版本控制url
curl https://example.com/api/lists/3 \
-H 'Accept: application/vnd.example.v2+json'
API URI保持不變。頭版本控制主要是經過自定義的Accept HTTP頭來完成的。核心URI仍然保持不變,可是能最好表示出API的資源,而且版本的更改將經過頭和響應類型傳遞。
沒有版本控制!
curl https://example.com/api/lists/3
你須要什麼版本?讓咱們擴展咱們的API以適應新的或調整的案例!放棄舊的框架,選擇創建和擴展。
中立觀點
每個方法都是合理的,若是有好的設計思路的話,它們均可以呈現優異的API。 最終,咱們但願它們都能實際運用起來,儘量快地傳輸信息。一個沒有版本控制的綠色API可能會變得混亂,因此咱們將遠離這一點。相反,咱們將接受URI和HTTP標頭中的版本控制。做爲一個轉折,咱們將使用一個自定義的HTTP頭。
爲了不出現連咱們本身都沒法瞭解爲何請求會如此混亂且冗長的狀況出現,讓咱們更深刻地瞭解一下爲何咱們要使用這種方法。咱們的方法是基於這樣一句格言:隨着太陽的升起,你的應用將會改變。
咱們來看一個例子。
MightyList
咱們正在爲虛構應用程序MightyList構建API。在它簡陋的早期,Mighty List容許用戶建立列表。它具備從URI提供的API做爲mightyapp.com/api/v1/。您可使用API來請求列表信息,以下所示:
curl https://mightyapp.com/api/v1/lists/3
...
{
"listId": "3",
"shopping": "Shoes, tie, umbrella, snorkel",
"leisure": "Skiing, surfing, snorkeling ",
"food": "bananas, peanut butter, spinach",
"cost": "One hundred dollars"
}
在開發咱們的應用程序時,咱們能夠指望更改兩種類型:小版本調整和大版本調整。咱們來看看一個小版本調整的例子,使用咱們上面的示例響應,其中list 3的GET請求返回了shopping, leisure, food和cost的字符串值。開發團隊但願調整數據模型,cost如今變成了整數而不是字符串了。
curl https://mightyapp.com/api/v1/lists/3
...
{
"listId": "3",
"shopping": "Shoes, tie, umbrella, snorkel",
"leisure": "Skiing, surfing, snorkeling ",
"food": "bananas, peanut butter, spinach",
"cost": 100
}
此更改會破壞咱們API的向後兼容性!若是有人將MightyList API應用到他們的應用程序中,那麼接收一個整數而不是字符串可能會致使他們的應用程序中斷。爲了不出現這種意外的狀況,任何破壞咱們向後兼容性的微小變化都須要對新版本進行bump version。
另外一個須要考慮的狀況是大版本調整:MightyList版本2正在進行中。lists將成爲superlists,咱們也添加了不少新的資源:bots,ai——等等許多奇特的東西。這個重大升級確定會對兼容性產生重大影響; 這是一個全新的應用!
這兩個示例都揭露了在改進API時如何保持URL是最新的難度。小版本修改是否會破壞咱們的URL版本?這樣最終會有不少版本。咱們但願保持向後兼容性,但隨着應用的不斷髮展,它將變得愈來愈困難。
在咱們討論這個問題以前,讓咱們定義一個安全的和向後兼容的API更改應該是什麼樣子的:
添加新資源。
添加新的事件類型。
爲響應添加新的屬性。
改變屬性的順序。
向現有方法添加可選參數。
當經過選項或全新的資源或事件參數添加新事物時,您可徹底不用擔憂與客戶端創建的協議,由於它很是穩定,也不會產生任何變化。他們能夠繼續訪問API資源,也會獲得預期的響應。若是咱們更改了現有資源或預期的響應內容,咱們須要在API版本中把這種更改給展現出來。
爲了使咱們的應用程序的狀態清晰,咱們但願在URI中有一個表示基本產品版本的版本;當您的產品從根本上改變時,URI版本將會更改。 MightyList V1使用/ api / v1 /。 MightyList V2使用/ api / v2 /。
爲了使咱們的API的當前版本清晰,咱們將使用自定義的HTTP頭來表示較小的修訂。這相似於讓用戶請求應用程序版本V2.x。X是API的版本。
在兩個地方進行版本控制是一種實用的作法;您的應用程序將迭代,而且老是有可能變成更大的東西。咱們來看看Fly如何輕鬆地作到這一點。
Superfly API版本控制
在Fly裏面,每一個站點都由多個後端組成。您可能在GitHub上有一個靜態頁面,應用程序使用了Kubernetes集羣或Heroku部署,而且還用了一個或多個數據庫對數據進行管理。
構建API時,您能夠經過對API進行解耦,並將其做爲本身的後端主機,這樣API的可擴展性和負載平衡的優點就會獲得改善。對API解耦也使得版本控制變得相對容易一點。
首先,咱們將爲最初的API/api/v1/添加一個新的後端。 咱們將指定相關路徑去匹配/api/v1/。若是有多個冗餘實例須要負載平衡,咱們能夠將它們視爲獨立的後端進行添加,設置相同的路徑,而後調整優先級。若是想要實現這種想法,咱們可使用Fly Middleware根據設備或地理信息,將用戶路由到各類API後端。
上面咱們建立了一個基線API端點。咱們還但願爲API V1的最新版本建立一個後端。咱們將以04-05-2017爲終點。在此以後,咱們能夠設置API路由規則。
如今,要爲第二個後端配置FLY路由規則,以便讓那些附加了自定義頭文件的用戶能夠收到最新版本的API。咱們將使用頭名稱API-Version,由於它能讓用戶一眼看出其含義,讓用戶容易記住,也比較清晰。APIAPI-Version頭文件將是年月日或04-05-2017的形式。這樣作將容許咱們爲API建立一個公共的變動日誌。用戶能夠經過更改日期來獲取他們須要的端點。
太使人興奮了!咱們已經將API-version設置爲04-05-2017,若是頭文件中出現了這些信息,用戶就會被路由到API V1 - 04-05-2017的後端。用戶如今能夠選擇請求API的特定時間點,同時保留從example.com/api/v1 URI獲取原始API V1的能力。您能夠查看咱們第一個API後端的原始路由規則:
總結
讓咱們回顧一下:不一樣的API有不一樣的端點。用戶能夠查詢最初的API,或者添加定製的頭文件來接收特定的版本。若是應用程序進行了一次大版本的調整,咱們將正式地將URI修改成V2。
在進行迭代改進時,咱們也會按照修改的日期同時建立一個端點,並容許用戶將日期頭文件信息附加到上面。而後,咱們能夠選擇舊版本能夠保留多久,免費催收系統之後在不考慮向後兼容性以及不影響用戶使用的狀況下,能夠選擇合適的時間刪除它們。
在設計API版本時,您能夠應用許多不一樣的理念。使用本文中的實例,您能夠看到基於Fly頭文件或URI後端路由的這些靈活性,可讓你實現關於「PI體系結構和版本控制方案」最瘋狂的夢想。