微服务接口设计规范
1 接口評價標準
一個好的接口設計通常需要滿足以下幾點:
簡單:滿足需求的同時,越簡單越好。
易懂:優秀的API可讀性好,盡量做到不需要文檔就能讀懂接口名稱、參數的大概含義,提供給第三方的的接口要進行詳細地描述。包括參數的取值范圍、錯誤碼、異常返回規則、SLA相關指標等。
一致:對于同一公司、站點提供的API,最好有同一的規則,讓開發者只要看過幾個API后,基本能猜到剩余API的含義。
穩定:最好在開始的時候就考慮好,不要輕易修改API,否則會給使用方造成麻煩。
安全:設計時要考慮超出預期的情況如何處理,給出被限流的情況。如果提供給第三方,則要考慮如何認證。
2 接口設計原則
- 單一職責
單一性是指接口要做的事情應該是一個比較單一的事情,比如登陸接口,登陸完成應該只是返回登陸成功以后一些用戶信息即可。 - 開閉原則
對擴展開放,對修改關閉。需對變化封裝:
(1)將相同的變化封裝到一個接口或抽象類中 ;
(2)將不同的變化封裝到不同的接口或抽象類中,不應該有兩個不同的變化出現在同一個接口或抽象類中。 封裝變化,也就是受保護的變化,找出預計有變化或不穩定的點,為這些變化點創建穩定的接口。
-
接口隔離原則
使用多個專門的接口,而不使用單一的總接口。 其實接口隔離原則說白了就是單一職責的擴展。
對于一個比較細化的接口,更有利于書寫單元測試,也更有利于調試。 -
高內聚低耦合
一個接口要包含完整的業務功能,而不同接口之間的業務關聯要盡可能的小。 -
安全性原則
安全性問題是一個接口必須要保證的規范,可使用token(常用參數appid,appkey,timestamp,nonce,sign)、白名單、防刷、限流、隔離等手段保證接口調用的合法合規合理調用。 -
兼容性原則
接口設計要盡量考慮接口不同版本的兼容性,盡量避免升級的過程中不出現兼容性問題。
如果修改API不可避免,那么最好是通過增加接口而不是修改已有接口來兼容。如果一定要改變已有接口,也要通過明確的版本號加以區分。
3 接口設計方法論
接口設計時,需要重點考慮一下問題:
- 接口的命名。
- 請求參數。
- 支持的協議。
- TPS、并發數、響應時長。
- 數據存儲。DB選型、緩存選型。
- 是否需要依賴于第三方。
- 接口是否拆分。
- 接口是否需要冪等。
- 防刷。
- 接口限流、降級。
- 負載均衡器支持。
- 如何部署。
- 是否需要服務治理。
- 是否存在單點。
- 接口是否資源包、預加載還是內置。
- 是否需要本地緩存。
- 是否需要分布式緩存、緩存穿透怎么辦。
- 是否需要白名單。
- 架構設計時,可以根據場景的應用情況來做checklist。
4 Dubbo接口規范
4.1 Dubbo協議適用范圍
Dubbo缺省協議采用單一長連接和NIO異步通信,適合于小數據量(傳入傳出參數數據包建議小于100k)大并發的服務調用。
反之,Dubbo缺省協議不適合傳送大數據量的服務,比如傳文件,傳視頻等,除非請求量很低。
4.2 命名規范
com.xxx.xxdomain.子系統.自定義接口名
4.3 粒度
- 對外服務接口盡可能大粒度,每個服務方法應代表一個功能,而不是某功能的一個步驟,否則將地面臨分布式事務問題,Dubbo暫未原生提供分布式事務支持,同時也可以減少網絡交互。
- 服務接口建議以業務場景為單位劃分,并對相近的業務做抽象,防止接口數量爆炸。
- 不建議使用過于抽象的通用接口,如Map query(Map),這樣的接口沒有明確語義,會給后期維護帶來不便。
4.4 版本及兼容性
- 每個接口都應定義版本號,為后續不兼容升級提供可能。
- 建議使用兩位版本號,第一位主版本號,第二位次版本號,只有不兼容時才需要變更服務主版本。
- 當不兼容時,先升級一半提供者為新版本(通常在驗證或低壓力時間段),再將消費者全部升級為新版本,然后將剩下的一半提供者升為新版本。
- 服務接口增加方法,或服務模型增加字段,可向后兼容。
- 刪除方法或刪除字段,將不再兼容,枚舉類型新增字段也不兼容,需要通過變更版本號升級。
4.5 異常
- 建議使用異常報告錯誤,而不是返回錯誤碼,異常能攜帶更多信息,并且語義更又好。
- 如果擔心性能問題,在必要時,可以override掉異常類的fillInStackTrace()方法為空方法,使其不拷貝棧信息。
- 查詢方法不建議拋出checked異常,否則調用方在查詢時將過多的try…catch,并且不能進行有效處理。
- 服務提供方不應將DAO或SQL等異常拋給消費方,應在服務實現中對消費方不關心的異常進行包裝,否則可能出現消費方無法反序列化相應異常。
4.6 其它Tips
- 服務參數及返回值建議使用POJO對象。
- 建議Provider端對輸入參數進行校驗。
- Provider端盡量多配置Consumer端的屬性,讓provider的實現者一開始就思考provider端的SLA。
5 RESTful接口規范
5.1 協議
考慮到服務的安全性,建議使用https作為API的通信協議,當然http也是可以的。
5.2 URL約定
URL格式:http(s)😕/server.com/{domain}/{version}/api-name。
| 獲取 | get | get{XXX} |
| 新增 | add | add{XXX} |
| 修改 | update | update{XXX} |
| 保存 | save | save{XXX} |
| 刪除 | delete | delete{XXX} |
| 上傳 | upload | upload{XXX} |
5.3 數據格式
使用JSON作為微服務提交和返回數據的通用語言。
使用HTTP狀態碼來傳達服務調用的狀態。
5.4 請求參數
- 動詞釋義
| GET | 獲取數據 |
| POST | 新增數據 |
| PUT | 更新數據 |
| DELETE | 刪除數據 |
- 請求參數
1)Query:是指請求的參數,一般是指URL中?后面的參數。
2)Header:請求頭,存放公共參數、requestId、token、加密字段等。
3)Body:請求體,存放請求接口的參數數據。
-
版本信息
考慮到服務接口的平滑升級,可以將API的版本號放入URL,也可以將版本號放在HTTP頭信息中,但不如放入URL方便和直觀。 -
過濾信息
請求信息應該為集合提供過濾、排序、選擇和分頁等功能。
1)Filtering過濾
使用唯一的查詢參數進行過濾:如GET /cars?color=red 返回紅色的cars。
2)Sorting排序
允許針對多個字段排序:如GET /cars?sort=-manufactorer,+model #這是返回根據生產者降序和模型升序排列的car集合。3)Field selection選擇
給API消費者一個選擇字段的能力,這會降低網絡流量,提高API可用性。如GET /cars?fields=manufacturer,model,id,color。4)Paging分頁
使用 limit 和offset.實現分頁。如GET /cars?offset=10&limit=5。有時候為了將總數發給客戶端,可以使用訂制的HTTP頭:如X-Total-Count。5.5 返回參數
- 返回包體格式
| code | Number | 結果碼 | |
| showMsg | String | 顯示信息 | |
| errorMsg | String | 錯誤信息 | |
| data | Object | 數據 | JSON 格式 |
- 返回碼
http協議標準返回碼及含義如下:
200 OK [GET]:服務器成功返回用戶請求的數據,該操作是冪等的(Idempotent)
201 CREATED [POST/PUT/PATCH]:用戶新建或修改數據成功
202 Accepted [*]:表示一個請求已經進入后臺排隊(異步任務)
204 NO CONTENT [DELETE]:用戶刪除數據成功
400 INVALID REQUEST [POST/PUT/PATCH]:用戶發出的請求有錯誤,服務器沒有進行新建或修改數據的操作,該操作是冪等的
401 Unauthorized [*]:表示用戶沒有權限(令牌、用戶名、密碼錯誤)
403 Forbidden [*] 表示用戶得到授權(與401錯誤相對),但是訪問是被禁止的
404 NOT FOUND [*]:用戶發出的請求針對的是不存在的記錄,服務器沒有進行操作,該操作是冪等的
406 Not Acceptable [GET]:用戶請求的格式不可得(比如用戶請求JSON格式,但是只有XML格式)
410 Gone [GET]:用戶請求的資源被永久刪除,且不會再得到的
422 Unprocesable entity [POST/PUT/PATCH] 當創建一個對象時,發生一個驗證錯誤
500 INTERNAL SERVER ERROR [*]:服務器發生錯誤,用戶將無法判斷發出的請求是否成功
- 冪等說明
冪等:請求一次和請求多次的效果是一樣的。
GET:由于GET請求僅僅是獲取資源 并不修改資源,所以能保證冪等。
PUT:同樣的請求,修改一次和修改多次是一樣的,能保證冪等。
DEL:同理,能保證冪等。但是多次請求,只有第一次能返回200,其他都應該是404。
POST:不冪等,多次請求會在數據庫表中生成多條記錄。
因此,對POST的接口冪等性需要在業務代碼上去實現。
總結
- 上一篇: 四轴六轴机械臂基础运动仿真实验(Matl
- 下一篇: EFCore 的 DbFirst 模式