您的位置:首頁 >熱評 >

如何把一個接口設計好?

2023-09-01 07:53:38 來源:博客園

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

很多人覺得這不就是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對齊方案。實現需求的過程中,有什么問題,需要及時跟產品溝通。需要跟客戶端對齊接口,一定不能上來就自己埋頭把接口定義完了。種種場景,學會溝通是非常重要的,有效、高效溝通不僅會帶來愉悅心情,開發起來很順暢,也會提高人際關系。

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

作者:京東零售 李澤陽

來源:京東云開發者社區 轉載請注明來源

關鍵詞: