一、背景
到新公司有一段時間了發現公司的服務接口設計的過於復雜、易用性方面也不太方便,結合以前的經驗做些調整優化,以此記錄遇到的注意事項。
我們知道服務接口API使用方式:1、被使用方使用 2、依賴於別的服務接口 3、既被使用方使用又依賴於別的服務接口。要提高服務的可用性、穩定性,會涉及到業務應用系統的分布式架構緩存、數據庫等多方面,本文只從服務接口api層面討論。在實際的操作過程中發現和《如何避免故障?》很多處理方式不謀而合。那么從上面三種使用場景討論具體的處理策略。
二、被使用方使用場景
1、服務接口api參數易用性
參數定義:定義具有明確含義的參數名稱,實際情況中發現竟然還有o、p的參數。
參數的類型:每一個參數明確的數據類型,不要清一色的String而盡量給每一個參數定義不同合適的數據類型,避免api方法的誤用和減少了數據類型的轉換。
參數的數量:服務接口api中參數個數不宜太多,如果個數太多那就建議使用參數類吧。在實際情況中有七八個參數,使用參數類是不是清爽的很多。
2、服務接口api良好的使用說明
參數的使用說明就不再贅述了。着重說下下面情況:
參數有傳參中文:某些情況下我們的接口會傳參中文,中文參數就會有編碼要求UTF-8,GBK,如果不約束具體的編碼,可能接口就會有亂碼甚至保存異常。如ERROR 1366 (HY000)
無分頁:某些業務邏輯中無分頁,但默認情況下要返回前N條數據,如果沒有說明就會造成使用方的困惑。實際中我們的一個接口默認提供前12條數據,而使用方知道數據不止12條,徒增溝通時間成本。
有分頁:定義好默認一頁記錄數,還是允許使用方自行定義返回記錄數。根據業務場景還是要約束一頁記錄數,避免數量過大而影響性能。
因此我們要對接口api制定詳細的良好的使用說明。
3、服務接口api異常信息
明確詳細的異常信息在調試api快速定位解決問題的利器了,因此我們必須設計良好的異常信息,以便自己記錄和提供給使用方參考。
- 參數檢驗異常
為了服務接口的安全,我們都會把參數做校驗及轉換。如參數id是整型類型的 id=81 我們就會做整型類型的校驗,如果不是整型的就會返回參數id必須是整型的提示信息及自定義的錯誤代碼。
- 業務邏輯異常
在內部處理業務邏輯時,如果出現異常我們也要將記錄相應的異常信息及自定義的錯誤代碼,而不能只給使用方提示服務器發生錯誤這樣信息。估計看到這樣的信息會抓狂,我們的目的是當使用方拿到錯誤代碼對照接口api使用說明就會很快定位到問題所在。
我們可以定義異常信息格式:
{
"requestId" : 1001, "code" : 1024, "message" : "Paramters Validation Failed", "errors" : [ { "code" : 5432, "field" : "tkey", "message" : "Required argument tkey: expect [type: java.lang.String]" }, { "code" : 5622, "field" : "token", "message" : "token cannot be blank" } ] }
4、服務接口api粒度
在設計接口api時,api粒度不宜過細也不宜過粗,根據具體的業務邏輯進行設計。過細的話不僅api性能差也會徒增服務器壓力。如獲取某個專輯信息及其中的視頻信息,我們實際中只有獲取某個專輯信息的接口和專輯中的視頻信息的接口。和同事討論才得知當時按照“單一職責”原則進行設計的。能夠按照“單一職責”原則進行設計固然是好,但是也不能太死板應該在原則下靈活變通。現在我們在增加一個接口api(同時返回某個專輯信息及其中的視頻信息)性能是不是會優於上述兩種接口組合使用哪?
5、服務接口api版本演進或版本控制
隨着業務的發展,老的接口api已不能滿足新的業務邏輯,此時是改造老的接口還是增加新的接口?如果在老的接口中進行改造來支持新的業務邏輯,但是不得不維護老的業務邏輯,無形中增加工作量和難度。實際中我們可以新增加接口api,老的api和新的api同時提供服務,然后將老的api平滑過度到新的api。
我們可以定義api版本格式
/ms/api/v2/...
6、服務接口api業務功能降級
我們先來看下視頻網站一部影片都會有那些相關數據?
一部影片都會有影片正片信息和影片相關的視頻片段(預告片、花絮等)
我們就可以有以下的處理思路:
- 設置降級開關
- 當合法的請求量瞬間爆滿,服務接口api的性能嚴重下降時,自動或手動打開降級開關至返回影片的正片信息,而相關片段(周邊視頻)就可以暫時不返回數據
- 當服務器壓力減弱時,關閉降級開關在返回相關片段(周邊視頻)數據。
7、服務接口api限流
服務接口api的降級和限流都是流量控制的處理策略,同時也是系統的自我保護策略。雖然犧牲了一部分業務功能和高並發量,但換來的系統的可用性。
限流請參看之前的文章《服務接口API限流 Rate Limit》。
三、依賴於第三方服務接口場景
1、設置合理的超時時間
如果超時就應該斷掉請求連接,把業務處理的線程讓給別的請求,加快處理同時也減輕了所依賴服務的壓力。
2、合理使用重試機制
根據所依賴服務接口返回的信息合理的使用重試機制,如果所依賴的服務返回業務處理異常在使用重試機制也毫無意義,只會徒增所依賴服務器的壓力。
3、異步調用服務接口
我們的服務接口中都會穿插着業務邏輯,如果使用httpsyncclient異步調用服務接口數據,此時處理自己的業務邏輯在結合異步返回的數據組織最終的業務數據。從而提高了服務接口處理能力。
4、依賴服務接口
如果所依賴的服務接口crash,那么自己的服務接口也無法正常提供數據。
根據依賴的服務接口數據的時效性,做出相應的處理策略:
a、數據時效性不高,可以對依賴接口返回的數據做緩存處理。通過定時任務刷新緩存數據或者定義緩存數據失效時間等方式。
b、數據時效性非常高,對於這種情況 --- 痛點。 如果您有好的處理策略請指點。
四、接口調用過程異常處理
1、接口調用過程異常原因
- 通訊框架異常
a、網絡通訊錯誤
系統錯誤會導致無法預測的異常產生,還的具體取決於RPC服務的實現方式。對於這種錯誤,唯一的處理方式只有:另外找時間或機會重試
- 業務系統異常
a、系統錯誤
服務應用在處理內部邏輯時出現了無法控制的錯誤,常見場景:
-
- 網絡訪問失敗
- 數據庫訪問失敗
- 文件寫入失
一般這種錯誤,采用重試機制就能很好得到解決。
b、業務錯誤
調用方傳遞了違背業務規則的參數從而導致了業務處理失敗。
2、接口調用過程異常處理
- 定義自定義異常
這個異常主要用於收縮和屏蔽服務層的具體錯誤信息,當服務端遇到無法處理的錯誤情況時,需要繼續向客戶端外拋,讓客戶端來擇機進行重試。客戶端亦可通過SelfException快速判斷當前業務中斷的原因來自於SelfService的失敗。
我們可以在返回的結果中增加isReTry,來告訴調用方服務接口是否需要重試機制。
五、總結
合理的服務接口設計和良好的服務接口使用,都會提高服務接口可用性和穩定性、易用性、健壯性。
服務接口異常處理解決方案:
調用情況 | isSuccess | errorCode | isReTry | throw SelfException | throw Exception | 調用方處理 |
框架異常 | / | / | / | true | 重試 | |
系統異常 | / | / | true | / | 重試 | |
業務異常 | false | true | true | true | / | 重試 |
業務異常 | false | true | false | true | / | / |
成功返回 | true | false | / | / | / | / |
參考延伸閱讀:http://www.cnblogs.com/LBSer/p/4753112.html
由於本人經驗有限,文章中難免會有錯誤,請瀏覽文章的您指正或有不同的觀點共同探討!