API設(shè)計的幾條原則 | IDCF

內(nèi)容來源:ThoughtWorks洞見 作者:少個分號

API 設(shè)計是微服務(wù)設(shè)計中非常重要的環(huán)節(jié),代表服務(wù)之間交互的方式,會影響服務(wù)之間的集成。通常來說,一個好的 API 設(shè)計需要滿足兩個主要的目的。
API 本身的含義指應(yīng)用程序接口,包括所依賴的庫、平臺、操作系統(tǒng)提供的能力都可以叫做 API。我們在討論微服務(wù)場景下的 API 設(shè)計都是指 WEB API,一般的實現(xiàn)有 RESTful、RPC等。API 代表了一個微服務(wù)實例對外提供的能力,因此 API 的傳輸格式(XML、JSON)對我們在設(shè)計 API 時的影響并不大。
API 設(shè)計是微服務(wù)設(shè)計中非常重要的環(huán)節(jié),代表服務(wù)之間交互的方式,會影響服務(wù)之間的集成。通常來說,一個好的 API 設(shè)計需要滿足兩個主要的目的:
平臺獨(dú)立性。任何客戶端都能消費(fèi) API,而不需要關(guān)注系統(tǒng)內(nèi)部實現(xiàn)。API 應(yīng)該使用標(biāo)準(zhǔn)的協(xié)議和消息格式對外部提供服務(wù)。傳輸協(xié)議和傳輸格式不應(yīng)該侵入到業(yè)務(wù)邏輯中,也就是系統(tǒng)應(yīng)該具備隨時支持不同傳輸協(xié)議和消息格式的能力。 系統(tǒng)可靠性。在 API 已經(jīng)被發(fā)布和非 API 版本改變的情況下,API 應(yīng)該對契約負(fù)責(zé),不應(yīng)該導(dǎo)致數(shù)據(jù)格式發(fā)生破壞性的修改。在 API 需要重大更新時,使用版本升級的方式修改,并對舊版本預(yù)留下線時間窗口。
實踐中發(fā)現(xiàn),API 設(shè)計是一件很難的事情,同時也很難衡量設(shè)計是否優(yōu)秀。根據(jù)系統(tǒng)設(shè)計和消費(fèi)者的角度,給出了一些簡單的設(shè)計原則。
使用成熟度合適的 RESTful API
RESTful 風(fēng)格的 API 具有一些天然的優(yōu)勢,例如通過 HTTP 協(xié)議降低了客戶端的耦合,具有極好的開放性。因此越來越多的開發(fā)者使用 RESTful 這種風(fēng)格設(shè)計 API,但是 RESTful 只能算是一個設(shè)計思想或理念,不是一個 API 規(guī)范,沒有一些具體的約束條件。
因此在設(shè)計 RESTful 風(fēng)格的 API 時候,需要參考 RESTful 成熟度模型。

根據(jù)自己的應(yīng)用場景選擇對應(yīng)的成熟度模型,一般來說系統(tǒng)成熟度模型在 Level 2左右。
避免簡單封裝
API應(yīng)該服務(wù)業(yè)務(wù)能力的封裝,避免簡單封裝讓API徹底變成了數(shù)據(jù)庫操作接口。例如標(biāo)記訂單狀態(tài)為已支付,應(yīng)該提供形如POST /orders/1/pay這樣的API。而非PATCH /orders/1,然后通過具體的字段更新訂單。
訂單狀態(tài)這個內(nèi)部使用的字段。關(guān)注點(diǎn)分離
/users/1/updateURI。User這個類:{
"username": "用戶名",
"password": "密碼"
}這個對象在修改用戶名的時候,password是不必要的,但是在修改密碼的操作中,一個password字段卻不夠用了,可能還需要confirmPassword。
{
"username": "用戶名",
"password":"密碼",
"confirmPassword":"重復(fù)密碼"
}// POST /users/{userId}/password
{
"password":"密碼",
"confirmPassword":"重復(fù)密碼"
}
// PATCH /users/{userId}
{
"username":"用戶名",
"xxxx":"其他可更新的字段"
}完全窮盡,彼此獨(dú)立
PUT /orders/1/order-items/1這樣的接口去修改訂單項,接口PUT /orders/1就不應(yīng)該具備處理某一個order-item的能力。
版本化
URI 前綴 Header Query
比較推薦的做法是使用 URI 前綴,例如/v1/users/表達(dá)獲取 v1 版本下的用戶列表。
/users/1/updateV2。這樣做的缺陷是版本信息侵入到業(yè)務(wù)邏輯中,對路由的統(tǒng)一管理帶來不便。合理命名
盡可能和領(lǐng)域名詞保持一致,例如聚合根、實體、事件等 RESTful 設(shè)計的 URI 中使用名詞復(fù)數(shù) 盡可能不要過度簡寫,例如將 user 簡寫成 usr盡可能使用不需要編碼的字符
用領(lǐng)域名詞來對 API 設(shè)計命名不是一件特別難的事情。識別出的領(lǐng)域名詞可以直接作為 URI 來使用。如果存在多個單詞的連接可以使用中橫線,例如/orders/1/order-items
安全

錯誤的調(diào)用方式 接口濫用 瀏覽器消費(fèi) API 時因安全漏洞導(dǎo)致的非法訪問
API設(shè)計評審清單
URI 命名是否通過聚合根和實體統(tǒng)一 URI 命名是否采用名詞復(fù)數(shù)和連接線 URI 命名是否都是單詞小寫 URI 是否暴露了不必要的信息,例如 /cgi-binURI 規(guī)則是否統(tǒng)一
資源提供的能力是否彼此獨(dú)立
URI 是否存在需要編碼的字符
請求和返回的參數(shù)是否不多不少
資源的 ID 參數(shù)是否通過 PATH 參數(shù)傳遞
認(rèn)證和授權(quán)信息是否暴露到 query 參數(shù)中
參數(shù)是否使用奇怪的縮寫
參數(shù)和響應(yīng)數(shù)據(jù)中的字段命名統(tǒng)一
是否存在無意義的對象包裝 例如
{"data":{}'}出錯時是否破壞約定的數(shù)據(jù)結(jié)構(gòu)
是否使用合適的狀態(tài)碼
是否使用合適的媒體類型
響應(yīng)數(shù)據(jù)的單復(fù)是否和數(shù)據(jù)內(nèi)容一致
響應(yīng)頭中是否有緩存信息
是否進(jìn)行了版本管理
版本信息是否作為 URI 的前綴存在
是否提供 API 服務(wù)期限
是否提供了 API 返回所有 API 的索引
是否進(jìn)行了認(rèn)證和授權(quán)
是否采用 HTTPS
是否檢查了非法參數(shù)
是否增加安全性的頭部
是否有限流策略
是否支持 CORS
響應(yīng)中的時間格式是否采用
ISO 8601標(biāo)準(zhǔn)是否存在越權(quán)訪問


