如何把一個接口設計好? | 京東雲技術團隊

如何設計一個接口?是在我們日常開發或者面試時經常問及的一個話題。

很多人覺得這不就是CRUD,能實現不就行了。單純實現來說,並非難事,但要做到易用、易擴展、易維護並不是一件簡單的事。這裏並不強調一些個接口設計的原則或者設計方法,僅從如何設計一個好的接口出發,簡單討論。

1、命名規範

我們寫代碼,不僅僅是爲了實現當前的功能,也要有利於後面的維護。所謂的維護,就是代碼不僅僅是寫給自己看的,也是給別人看的。所以接口定義要清晰易懂、命名規範。

除了接口、方法、出入參命名規範,也要注意代碼規範問題。一開始接觸到各種代碼壞味道的小夥伴,大多都會覺得這些規範很多餘、很煩人,但實際上,這些好的編碼習慣是讓大家都能按照基本規約開發,易於閱讀易於維護的基礎。

在接口定義時,也請注意接口功能的單一性。其實這也是微服務的一些思想,接口功能的單一職責、明確簡單。比如登錄接口,它做的事情就是校驗賬戶名和密碼相關;訂單服務、積分服務、商品信息相關的接口都是劃分開的。

2、參數校驗

入參出參校驗是每個程序員必備的基本素養。你設計的接口,必須先校驗參數。比如入參是否允許爲空、入參長度要求、入參是否在枚舉值範圍內等等。日常開發中,很多低級bug都是不校驗參數導致的。

提到參數,就必須提到接口狀態和錯誤碼。無論是失敗還是成功,一個完備的接口都應該告訴調用方返回信息。如果接口失敗,具體失敗的原因是什麼,這就需要定義明確的錯誤碼和對應描述。同時,儘量對報錯信息進行封裝,不要直接將服務端異常信息拋出去。

3、監控/性能

如何評判一個接口的性能就必須要有監控,這對於服務端監視接口性能和異常報警至關重要。調用次數、可用率、TP99、TP999等監視指標,極其重要的核心接口,還需要細分至秒級監控加以標識。

一個接口的性能不單單隻看自己業務邏輯,外部遠程調用也是消耗性能的重要部分。如果你調用第三方接口或者遠程服務,就需要考慮異常和超時。如果異常了,怎麼處理,是重試還是當作失敗還是告警處理。如果重試,重試幾次?這就需要站在業務角度思考這個問題。這些措施也是直接影響當前接口性能。

提高性能的利器還可以考慮緩存。緩存用得好,可以承載更多的請求,提升查詢效率,減少數據庫的壓力。但是使用緩存需要考慮緩存和數據庫一致性保證、緩存擊穿等問題。

4、日誌

接口的關鍵代碼,要有日誌的保駕護航。首先日誌級別需要合理使用:error > warn > info > debug。

其次日誌信息包含哪些呢,核心代碼塊調用前的入參打印、接口調用後的異常捕獲日誌等。需要注意的是,如果日誌中涉及比較大的JSON富文本,請使用log.isInfoEnable(),在高併發和複雜log信息拼接的情況下,使用這種標準的方法輸出log能夠省去不小的系統開銷。另外,如果構造log信息的過程需要大量字符串操作,建議使用StringBuilder來完成字符串拼接。

5、異常/超時

實現一個好的接口,離不開優雅的異常處理。比如異常匹配的順序,優先捕獲具體的異常;使用流時記得使用finally關閉流資源;

對於運行時錯誤,比如數據邊界越界、空指針也在日常開發中出現,該判斷、該校驗的還是一項不能少哦。

超時問題也經常會導致接口不可用。設置合理的超時時間,也是在保護你的接口。超時一般與重試搭配使用,不過請注意,設置超時時間時,需要充分考慮你的上下游設置的超時時間。比如一個請求率先訪問你的上游,而你的上游設置的超時時間是500ms,上游調用你的接口,但你設置的超時是2000ms,這其實就是無效超時時間。

對於接口耗時優化,也是有一些手段的,比如遠程串行改爲並行調用、單次調用改爲批量調用等等。但請注意儘量不在循環或者事務裏遠程調用。

6、異步

接口有些場景,使用異步更合理。舉個簡單的例子,對於一些運營操作的接口,往往需要記錄對應操作的操作日誌,記錄下是誰在什麼時間操作了什麼對象,便於追蹤“事發現場”。但是記錄操作日誌並不在接口主流程上,記錄操作日誌是否成功失敗也不應該影響正常主流程的執行,這個時候就應該考慮用消息隊列等方式進行異步解耦。

7、註釋

可以說,註釋也是良好代碼的重要組成部分。有些人,一直相信show me the code,卻不想寫一行註釋,認爲沒有必要。但是你無法保證代碼邏輯一直清晰、高效。如果是比較複雜的話,就建議把註釋寫清楚,這對於後續維護和縷清代碼邏輯很重要。

8、降級/限流

如今的請求調用基本都是分佈式調用鏈路,當分佈式系統中某個基礎服務不可用時,就會最終導致整個系統不可用,所以當下遊系統或者自身服務出現問題時,一定要考慮降級。如果做的更完備的話,還可以考慮熔斷。

同時,針對高併發的流量洪峯接口,必須考慮限流應對超出系統的承載能力挑戰。限流措施也同樣可以限制爬蟲,保護系統,丟棄多餘的請求。

9、安全

這裏說的安全,範圍可太大了。比如線性安全,很多人反手上來就是HashMap,因爲它是非線性安全的,可以考慮高併發下的ConcurrentHashMap。

如果前端重複請求,你的邏輯如何處理?是不是考慮接口去重處理(有時候是防刷處理)。簡單點,可以使用redis防重處理,同樣的請求,一定時間間隔內進行過濾。當然,對於一些併發不高的接口,比如轉賬類接口,推薦使用數據庫主鍵或者唯一索引。

如果消息隊列出現重複消費的情況,你的業務邏輯怎麼控制?是不是考慮冪等性校驗。

防重主要爲了避免產生重複數據,把重複請求攔截下來即可。而冪等設計除了攔截已經處理的請求,還要求每次相同的請求都返回一樣的結果。不過很多時候,它們的處理流程和方式是類似的。

還有一些其他安全方面的考慮,比如讀寫分離、代碼鎖的粒度控制、數據加密等等。

10、溝通

爲什麼要有溝通?又爲什麼把溝通放在最後呢?遇到一些技術難題,跟技術leader對齊方案。實現需求的過程中,有什麼問題,需要及時跟產品溝通。需要跟客戶端對齊接口,一定不能上來就自己埋頭把接口定義完了。種種場景,學會溝通是非常重要的,有效、高效溝通不僅會帶來愉悅心情,開發起來很順暢,也會提高人際關係。

好啦,以上就是根據自身經驗,對“如何設計一個接口?”問題的小小回答,如有不足,敬請指教。

作者:京東零售 李澤陽

來源:京東雲開發者社區 轉載請註明來源

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