微服務構建持久API的7大規則

前言

近年來,微服務架構發展迅速,SparkPost就是早期落地微服務架構公司之一,他們發現落地微服務過程中,不光需要考慮服務發現、服務註冊、服務調用跟蹤鏈等等架構問題,也需要重視微服務API的變更管理。微服務的一大特性就是獨立發佈,快速迭代,但前提是足夠穩定,他們在使用微服務構建API的過程中就遇到很多問題:
1. 客戶(微服務使用方)經常反饋API 升級變更後不可用,有時影響範圍不可控,導致該微服務上線延期,甚至線上故障,違背了微服務初衷
2. API參數變化或返回結果變化而導致客戶端行爲不一致,依賴客戶端需要大量重構,團隊不能專注在創新型工作
3. API 易用性差, 使用方技術棧不統一,各自進行API抽象及封裝,容易出錯
4. 缺少文檔及使用引導,需要大量支持工作
5. 閉門造車,產出微服務往往不能滿足需求,運行一段時間就會逐漸廢棄
SparkPost經過多年的探索與實踐,總結了大量最佳實踐,指導他們構建持久穩定的微服務API。現如今,它們的API被成千上萬的客戶使用,包括Pinterest、Zillow和Intercomto,每月發送超過150億封電子郵件。
在這篇文章中,我將回顧幾個選擇和最佳實踐。
 

七大原則

一、Restful是最好的,但要實用,不需要學究式

首先,也是最重要的一步,我們採取的步驟是決定使用REST作爲API。我們的理念是選擇以下三個要素作爲我們的API的基礎:。
1. HTTP : 這包括響應代碼和操作符。操作符包括POST、GET、PUT和DELETE,它們可以映射到基本CRUD(創建、讀取、更新、刪除)操作。
2. resources : 這些是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 根據這些規則和最佳實踐,爲他們的業務從提供現場電子郵件基礎設施到以完全基於雲計算的電子郵件發送服務提供了堅實的基礎。
 
原文鏈接:
https://devops.com/7-principles-for-using-microservices-to-build-an-api-that-lasts/
 

更多技術分享請關注公衆號:JFrog傑蛙DevOps

2月11日在線課堂:《容器持續交付流水線最佳實踐》
課堂收益:
1 .基於 Jenkins Pipeline,搭建 Docker 容器自動化持續交付流水線。
2 . 通過各階段自動化及手工測試的結果,形成多維度質量關卡,保障發佈包質量。
3 . 開發測試鏡像和生產鏡像分庫管理,通過質量關卡的鏡像升級到生產庫,生產庫的鏡像權限得到保障,避免鏡像被篡改。
4 .爲 Docker 鏡像構建進行持續的深度漏洞掃描,保證線上應用服務的安全。
5 . 爲應用依賴的數據庫等有狀態服務提供自動化地數據庫升級流程,規範自動化 CI/CD 流水線。
報名鏈接:https://www.bagevent.com/event/6358324

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章