
OAuth和OpenID Connect圖解指南
2018年Openapi Specification發布了3.0版本
圖片來源:https://swagger.io/
當你在考慮單個產品的API表現形式時,首先會選擇一種具體的API風格,常見的有RPC(Remote Procedure Call)和ROA(the Rest-Oriented Architecture)兩種模式,然后針對復雜的數據結構你會考慮使用什么樣的序列化協議,常見的包括Json/Xml/WSDL/Hessian等,用于封裝傳輸數據。但涉及到不同的產品時,在具體選型時考慮的問題可能就不太一樣了。
gRPC示意圖
圖片來源:https://www.grpc.io/docs/guides/
雖然RESTful設計風格曝光率很高,但并不是所有云服務商都選擇了完全遵循RESTful,例如AWS和阿里云RPC風格反而占了大多數,Google和Azure則RESTful居多。
Restful API的優勢是HTTP具備更好的易用性,讓異構系統更容易集成,且開發執行效率比較高,面向資源要求也比較高。而RPC API可以使用更廣泛的框架和方案,技術層面更底層也更為靈活,設計起來相對簡單,掌握起來有一定門檻,架構上更加復雜。
RESTful與RPC模式對比
不同的團隊根據實際情況和業務形態可能選擇不同的方案,那云服務作為一個整體應該強制統一好還是隨意選擇好?如果強制統一風格,有些適合RESTful風格的服務非要使用RPC的話,看起來就會比較丑陋,如果只是一個過程化的服務調用,往RESTful資源化設計方向去靠會比較困難。但如果不強制使用統一風格,會造成針對API的體系化支持會更加復雜,例如為兼容兩種風格SDK的自動化支持需要兩套代碼。
通常RESTful風格對API設計者的要求是比較高的,主要的難點在于面向資源設計要求開發者事先做好規劃,將后端數據模型與API服務模型相匹配。所以RESTful API的開發者應該是熟知系統整體實體關系模型的,很難想象一個不懂后臺業務的新手能設計出合理的API來。那么是不是RPC風格API就不需要面向資源設計了呢?從實踐中來看,并不是!RPC風格的API也需要資源模型來支持,在下一節中會重點分析。
所以,對于云服務商來說,選擇API風格時要考慮幾個問題:? ??
選定了具體設計模式后,就要努力做到統一,避免多種模式混雜帶來管理成本的上升。如果確實有必要兩種方式都支持(例如阿里云就同時支持RPC和ROA),就需要在技術上做好充分的準備。
用戶使用API來訪問云服務,本質上是想通過對某種云資源執行特定的操作來完成一個業務動作。Restful API需要面向資源設計眾所周知,那為什么RPC接口在云服務場景下也需要有資源模型呢?
RPC形式的API組織形態是領域和行為(對象和方法),隨著時間的推移,API越來越多最終形成一個龐大的集合。以阿里云為例,對外開放的OpenAPI數量已經達到10000多個,涵蓋了接近200個不同的產品。因為開發者必須單獨學習每個API,耗時又容易出錯,如果沒有一個脈絡的理解起來比較困難。如果有一套標準的資源模型,API就可以按照資源模型的維度分類組織,用戶使用起來也會有跡可循,體驗上會更好,否則面對如此多的API一點點學習無疑是個痛苦的過程。
另外,云服務并非單個服務的簡單排列,它是多個體系的橫向整合,總體對外呈現出有機連接。隨著云計算的發展,企業客戶對對云服務的要求不斷提高。最典型的就是當企業客戶大規模開始上云后,對虛擬化的云產品提出了各種管理需求,例如鑒權、編排、彈性伸縮等。
企業客戶對云服務的管理需求
以最常用的鑒權功能為例,客戶創建了一組云服務器來跑業務,運維人員需要有重啟服務器的權限,其他角色人員則不需要此類權限,針對RestartServer這么一個API就需要進行權限控制了。權限在云平臺中一般是中心式管理的,單獨的云產品不需要分別管理。如果統一處理鑒權,就需要知道當前API正在操作什么資源,與此相關的資源有哪些(例如與服務器有關的資源包括磁盤、網卡、網絡等關聯資源),然后針對所有相關資源逐一鑒權才能確認API操作是否可行。
上面提到的資源有兩個關鍵點,一是要有統一的資源模型,便于云產品對特定的API進行鑒權,二是要明確資源關系,當出現資源依賴的時候,需要關聯鑒權。在Google的API Guide中就明確提到需要資源關系,可以看出資源關系不僅僅是用來做API設計建模的,它對于平臺功能的實現也有至關重要的作用。不了解資源關系,有可能把多個資源封裝到一個API中,使用和變更都很痛苦,即便后期發現了問題再補救拆開,由于很多用戶已經在使用了,要付出的開發成本和溝通成本也是極大的,甚至成為不可能。所以清晰的資源模型有利于梳理清楚API體系。
定義清晰的實體關系圖有助于設計出更為完整的API
而且,明確的資源模型對于構建云上運維管理基礎設施至關重要,例如可以通過對資源打Tag來對資源進行分類管理(參考阿里云資源Tag),分組授權(參考阿里云資源組),資源審計(參考阿里云CloudConfig),類似開源軟件Terraform這樣的編排工具,由于有資源模型會更容易接入和使用。
所以,統一的資源模型對云服務的幫助是巨大的:
既然有這么多好處,那么眾多的云產品在實際設計API的時候能否堅持以資源為中心,充分考慮到上下游的需求就變成一個很大的挑戰了。
確定了設計模式和資源模型后,是時候進入到API設計細節了。諸如API名稱、參數名、屬性名稱、數據格式、錯誤碼之類的信息,看起來根本不是問題。單個產品問題還不大,只要保證內部風格一致即可,如果考慮到云服務多產品對外的整體體驗,就有必要考慮以下問題:
上述問題都是實際研發過程中要注意的,要全部羅列的話遠不止這些。API的用詞描述是云服務展現給外部用戶的第一印象,絕非隨意寫就。對人員有一定規模,內部有多條產品線的組織來說,如何協調組織的各個部分對外具有統一的體驗是個很大挑戰。
回顧下HTTP協議,最廣為認知的是對HTTP Mehod的約定,使用9個單詞就完成了對基本動作的規范,為開發者提供了清晰的思維模型:
Http Method 類型圖片來源:https://tools.ietf.org/html/rfc7231
同樣,在HTTP Header里面也對瀏覽器信息、語言、網絡連接屬性等做了詳細的規定,這樣開發者在使用HTTP服務的時候都有一個大致的約定,在關鍵信息上面不會有偏差,保障了異構系統的接口一致性。
因此云服務在管理API時應該考慮一些具體的規范,對命名規則、標準詞匯、最佳實踐模式、錯誤碼等信息都有明確的規定,同時用系統化、平臺化的手段來管理API,確保不走偏。設計風格不是云服務API設計中致命的問題,但是它關乎云服務外表形象,不可不察。
API是后端服務的外部表達,是服務就有可能出現問題,無論這個問題是可預期的還是不可預期的。如果只考慮功能本身功能特性,而忽視對異常情況的設計,當問題出現的時候業務本身可能無法感知造成服務異常,更重要的是站在客戶角度去看,不能有效獲取錯誤原因是非常痛苦的,很多時候只能束手無策,降低云服務提供商的整體口碑,甚至損害營收。
假設有個創建資源的API,每調用一次都會創建新的資源,考慮以下情況:
實踐中,如果不做好問題a的處理,可能會造成系統異常情況下大批資源被重復創建,有可能造成用戶或云服務商資損;問題b-e沒有處理好,可能會讓用戶陷入盲目等待或者盲目重試,使用體驗和效率極差;而f-g關系到自動化處理工具如何做到效率最大化,也關系到被集成的效率。
一個異步重試的狀態機
當出現異常的時候,API一般是要靠錯誤碼來告知用戶有什么問題。HTTP協議本身對錯誤碼做出了詳盡的規定,Restful的API要盡可能地符合標準。除此之外,云服務有必要在此基礎上進一步提供業務錯誤碼和錯誤信息,來描述錯誤具體的細節。
當前云服務的錯誤碼很多,看起來非常專業,但問題主要集中在以下幾個方面:
1.錯誤類型過多:錯誤碼越多客戶端處理起來越方便嗎?看一下HTTP的錯誤碼,只有5大類加幾十個子類的錯誤碼就涵蓋了所有場景,而通常大家耳熟能詳的無非是200、400、404、500、502等屈指可數的狀態碼。有的人考慮錯誤碼越多,客戶端可以switch/case一下針對每個錯誤碼做不同的操作,這個就見仁見智了,一般的程序員可能不會寫那么多的分支流程,必要性也不大。
2.錯誤信息表達不夠充分:相比于提供大量的錯誤碼,錯誤信息的明確表達更為重要。如果錯誤信息不夠詳細,作為用戶不了解細節無法掌控的云服務,幾乎是無法明確發生了什么,要么提工單,要么只能被動等待,客戶體驗很差。
3.業務錯誤碼與HTTP錯誤碼含義不匹配:例如參數錯誤應該返回4xx系列Code,返回5xx系列就不夠專業。即便是RPC風格的API,也要大致符合HTTP規則,否則可能會給一些依賴HTTP Code的系統造成誤導。網上有種思路覺得無論后臺響應如何,HTTP Code統統返回200,在Body里面的錯誤信息體現異常信息,這種不利于對接口的監控,因為監控系統很難通過識別消息體來鑒別功能是否正常響應。
4.相同錯誤不同云產品表達不一致:這會給客戶端開發造成困擾,增加開發工作量,不利于自動化集成,用戶體驗比較差。
5.錯誤碼應該是可枚舉集合:一個API能夠產生的錯誤碼類型應該是可預期的,即便是業務升級,也應該給客戶提供明確的錯誤碼列表,不能隨心所欲。因為用戶端需要明確知道可能會發生什么,而不是隨時可能出現不可預知的錯誤類型。如果錯誤類型不確定,就意味著針對錯誤碼分支處理基本是無效的。
要做好服務端容錯上述問題,需要從云服務整體層面加強API的容錯設計,做好錯誤碼規范,加強對錯誤信息的管理,來提升用戶體驗。
API都是不斷迭代的,通常都需要版本管理。云服務API的版本管理尤其重要,主要是以下原因:
針對API各種場景的管理,需要一套成熟的API管理平臺,照顧到各種場景的需求,也是一項不小的挑戰。
API如何開放看起來是奇怪的問題,難道API做出來不就是開放給別人用的嗎?做好就開放就開放啊?但在云服務場景下,情況會更復雜一點!
產品技術都是在不斷迭代的,功能始終在增加,新的API層出不窮。從客戶視角來看,他們對已開發完畢的API是否開放的需求是什么?假設一個云產品有100個功能特性,20個只能保留在內部,官網上總共提供了80個特性,而公開API只開放了50個,這是用戶期望的狀態嗎?理想狀態應該是什么?
圍繞云服務有一個龐大的生態,除了普通的開發者,還有許多第三方服務商、企業客戶、開源工具。當我們考慮所有這些生態成員的需求時會發現:云服務自身擁有的功能集合與客戶能使用的功能集合之間的差異比較能體現產品的開放程度。這里的差異強調的是云服務已經擁有的,不包括云服務自身沒有的服務。客戶能使用的功能與云服務能提供的功能之間的差距越大,說明云產品的開放程度越低,因為很多功能都作為保留節目被雪藏了,導致客戶和第三方服務商無法享受與云廠商接近的服務,最終生態無法拓展。理想狀況是,云服務商自身能通過API使用的功能,客戶都能通過OpenAPI使用,內外看到的是一致的。
但具體到某個API應不應該開放,實踐中會做如下考慮:
針對這些問題,需要在API的管理機制上面下功夫,能夠區分不同的場景,并做好元數據的管理。針對API是否開放要有明確的規范和度量機制,確保該開放的API都可以開放,確保內外客戶看到的功能集合基本一致,才有利于云服務更好地被集成,在客戶的業務中發揮更大的作用。
在云服務場景中,API并非孤立存在:
首先,API發布以后,用戶要想順利地使用API,配套設施必不可少,SDK、文檔、工具鏈的集成都需要考慮到,這里的重點是如何保障準確性、及時性和一致性。開發工程師一般都不太喜歡寫文檔,專業寫文檔的又可能不太懂技術,再考慮到國際化的問題,就十分有挑戰了。SDK方面,一個API要有多種語言的實現,每種語言還要保障其專業性、可用性,非常考驗對開發人員編程語言掌握的深度和對API的理解,業界經常采用的自動化生成SDK的方式也會考驗對多語言的兼容能力。工具鏈比如阿里云的 API Explorer、CloudShell等產品也需要及時與API的最新狀態保持同步。
其次,云服務由于產品線眾多,如何讓用戶能夠快速學習使用API和相關工具,需要在教程、案例、運行時環境等諸多方面加強建設。圍繞云服務,已經發展出許多上層生態工具,例如terraform/ansible/spinnaker等開源軟件,它們能夠幫助云服務更好地使用起來,必須對它們提供支持,如何能夠快速覆蓋也對平臺開發能力是個考驗。
另外,API本身的質量保障也是非常重要的。一般都要考慮性能、穩定性、安全等方面的保障體系,通過壓測、監控、部署防護軟件等方式來確保API在服務的時候不會掉鏈子。傳統的套路在解決系統問題時非常有效,但具體到業務問題的時候就無能為力了。例如,一個創建服務器的API一般來說都是要求冪等的,怎么檢測該API實際上有沒有做到冪等呢?推而廣之,其他業務流程的正確性又如何保障呢?等API開放了發現問題再修復就為時已晚,顯然應該在上線前通過測試來發現這類問題。但是隨著業務的發展,如何能保障這類問題可以有統一的解決方案,能夠長期跟進及時發現風險避免損失呢?
阿里云API體系簡易圖
所謂量變引起質變,上述問題針對單個API的時候都好解決,但是當API規模達到成千上萬的時候,就必須通過平臺化、系統化的手段來解決了。例如,API服務可靠性SLA指標如果要達到4個9,需要制定明確的標準,并且有手段監控到所有API的運行結果,通過分析成功率來判斷其是否達到預期水平,這對云服務本身的底層系統建設提出了較高的要求。
所以,以API為中心完善相關體系,保障用戶體驗的一致性、及時性、穩定性、易用性是非常有挑戰的。
https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages
https://tools.ietf.org/html/rfc7231#section-4
https://www.cnblogs.com/sparkdev/p/10052310.html
https://www.grpc.io/docs/guides/
https://www.terraform.io/docs/index.html
http://www.grabsun.com/article/2015/1135807.html
文章轉自微信公眾號@阿里云開發者