微服務構建持久 API 的7大規則
客戶(微服務使用方)經常反饋 API 升級變更後不可用,有時影響範圍不可控,導致該微服務上線延期,甚至線上故障,違背了微服務初衷。
API 參數變化或返回結果變化而導致客戶端行為不一致,依賴客戶端需要大量重構,團隊不能專註在創新型工作。
API 易用性差, 使用方技術棧不統一,各自進行 API 抽象及封裝,容易出錯。
缺少文檔及使用引導,需要大量支持工作。
閉門造車,產出微服務往往不能滿足需求,運行一段時間就會逐漸廢棄。
SparkPost 經過多年的探索與實踐,總結了大量最佳實踐,指導他們構建持久穩定的微服務 API。現如今,它們的 API 被成千上萬的客戶使用,包括Pinterest、Zillow 和 Intercomto,每月發送超過150億封電子郵件。
在這篇文章中,我將回顧幾個選擇和最佳實踐。
RESTFUL 是最好的,但要實用,不需要學究式
首先,也是最重要的一步,我們采取的步驟是決定使用 REST 作為 API。我們的理念是選擇以下三個要素作為我們的 API 的基礎:
1.HTTP : 這包括響應代碼和操作符。操作符包括 POST、GET、PUT 和 DELETE,它們可以映射到基本 CRUD(創建、讀取、更新、刪除)操作。
2.EESOURCES : 這些是 HTTP 操作人員執行的實體。
3.JSON (JavaScript 對象表示法) : 這是一種通用的數據交換格式。
這三個元素提供了實用 REST API 所需的一切,包括簡單性、可移植性、互操作性和可修改性。在構建了 API 之後,用戶可以輕松地對其進行集成,而不考慮他們的編程語言,包括 C#、PHP 和 NODE.JS, JAVA,甚至是 SHELL 中的 CURL。他們可以不用擔心潛在的技術發展,包括多種微服務。
當我們創建 SparkPost API 時,我們試著不要太過學究式地使用純粹的 REST 模型,而是選擇易於使用。下面是兩個可能不遵循 RESTFUL 最佳實踐的示例:
1.GET /api/v1/account?include=usage
2.POST/api/v1/sending-domains/example.domain.com/verify
第一個示例使用查詢字符串參數來過濾實體中返回的內容。在第二個示例中,我們在終端名稱中使用“VERIFY”這個動詞,這可能不符合 RESTFUL。我們會討論每個新的用例,並盡力確保它的一致性和易於使用。
發展進化並管理變化
我們有許多開發人員和團隊在使用我們的 API 的微服務,並在持續的變更。當工程師確定它已經通過了我們的測試時,我們就會自動將變更部署到生產中。
我們很早就決定讓我們的 API 在使用慣例和如何管理變更方面保持一致。我們建立了一個治理小組,其中包括代表每個團隊的工程師、產品管理組的成員和 CTO。這個組建立了並強制我們遵守的 API 約定,並且是完全文檔化的。
文檔化的約定讓我們可以減少不一致,並且更容易定義每個新的端點。以下是我們建立的一些約定:
在單詞命名時,URL 路徑是帶有連字符的小寫字母,並且區分大小寫。
URL 查詢參數和 JSON 字段也是小寫的下劃線,並且是大小寫敏感的。
請求主體中的非預期查詢參數和 JSON 字段應該被忽略。
治理組還為如何進行更改以及允許哪些類型的更改設置了基本規則。有一些很好的 API 更改對用戶是有益的,並且不會破壞它們的集成,包括:
一個新的 API 資源、端點或現有資源上的操作。
一個新的可選參數或 JSON 字段。
在 JSON 響應主體中返回的新字段。
相反,一個破壞性的變化包括任何可能破壞用戶集成的東西,比如:
更改字段的數據類型。
一個新的必需參數或 JSON 字段。
刪除現有端點或請求方法。
現有資源方法的實質性行為差異,例如將選項的默認值改為“TRUE”
做任何修改時不要制造破壞
即使它們是修復 BUG 或不一致的結果,也應該避免發生修改。通常在這種特殊的情況下運行比破壞與客戶端的集成風險更大。如果變化是多樣的,我們會非常謹慎,尋找其他方法來實現我們的目標。有時可以通過簡單地允許用戶通過帳戶設置或 API 參數更改其行為來實現。
然而,總會有一種情況引入變化對我們用戶的利益勝過任何潛在的不利因素,將引入的變化。但是在這些情況下,我們遵循了這些最佳實踐:
我們分析了 API 日誌,以了解更改可能會影響多少用戶。
我們給用戶至少30到60天的提前警告。
我們發了一封郵件或發表了一篇博客文章,裏面包含了關於改變的詳細信息以及我們為什麽要做這些改變。
我們在 API 文檔中提供了升級指導。
“一個版本”規則
在過去的三年裏,我們對 API 進行了數千次的修改,現在仍然是第一個版本。我們很早就決定不將 API 的版本超過第一個版本,因為這樣做會增加不必要的復雜性,從而減慢用戶對我們最新和最強大功能的使用。對 API 的版本控制也會減緩開發和測試,讓監控變得復雜,讓用戶文檔變得混亂。
另外,我們的 API 沒有版本控制,這意味著我們可以避免圍繞主題的爭論。有三種方法可以實現 API 的版本,所有這些都有潛在的缺陷:
把這個版本放到 URL 中: 容易做,但是從語義的角度來看是一個不好的選擇,因為這個實體在 v1 和 v2 之間沒有變化。
添加一個自定義的標題 : 也很容易做,但是語義不強。
在 ACCEPT 標頭中放置這個版本: 語義強但是最復雜的方法。
使用客戶端庫來幫助非 JAVASCRIPT 用戶
我們的一些用戶更喜歡 PYTHON、C#、JAVA 或 PHP 而不是 JAVASCRIPT。我們通過維護客戶端庫(為其代碼提供易於使用的函數庫)將API集成到應用程序中,使其快速進行集成。
隨著時間的推移,我們的客戶庫已經發生了變化,我們也做了相應的版本。我們已經了解到,在包裝一個不斷增長的 API 時,抽象是很困難的,所以我們專註於提供一層薄薄的抽象,並使用一些語法快捷方式來簡化我們 API 的使用。這樣做可以讓我們的用戶快速地訪問我們任何 API,並且具有許多靈活性
“文檔優先”的策略
我們將我們的文檔視為代碼,並在編寫或更改一個 API 代碼行之前使用它來記錄我們的 API 更改。這樣做可以幫助我們執行我們的約定,使所有事情保持一致,並保持良好的客戶體驗。它還削減了支持成本。
我們在 GitHub 中維護我們的文檔,這使得技術和非技術用戶可以很容易地做出更改。我們還發現,更容易審查變更的方式。我們使用 API Blueprint Markdown 格式和 JEKYll 生成 HTML 文檔,以及一個名為 Algolia 的強大搜索服務。這樣做讓我們能夠提供更好的客戶體驗,包括移動設備。
對於那些不想“滾動升級自己”文檔的人來說,我們推薦 OPENAPI(以前稱為“Swagger”)、Apiary和 API Blueprint。避免使用不適合 REST API 文檔的工具是很重要的。我們建議在文檔中包含一個亮橙色的“在 POSTMAN 中運行”的按鈕,這樣可以很容易地試用一個 API,以及成功和失敗場景的例子。
聽取用戶的意見
最後,我們建議所有開發人員註意他們的用戶的反饋。SparkPost 有一個社區 Slack 的頻道,成千上萬的用戶可以方便地聯系我們的產品、支持、工程和執行管理團隊的成員。我們也有一個專門的開發人員關系團隊,他們專註於與開發人員社區的合作。所有這些都讓我們能更好傾聽用戶的意見,並將他們的反饋整合到我們的 API 中。
總結
隨著微服務架構的發展,微服務快速增長,有的企業內部運維了超過1000的微服務,且仍在不斷增長,每個微服務包含數十 API,如何持續管理微服務 API 變化將成為企業的關註點,SparkPost 根據這些規則和最佳實踐,為他們的業務從提供現場電子郵件基礎設施到以完全基於雲計算的電子郵件發送服務提供了堅實的基礎。
微服務構建持久 API 的7大規則