如何設(shè)計(jì)一個(gè)接口?是在我們?nèi)粘i_發(fā)或者面試時(shí)經(jīng)常問及的一個(gè)話題。
很多人覺得這不就是CRUD,能實(shí)現(xiàn)不就行了。單純實(shí)現(xiàn)來說,并非難事,但要做到易用、易擴(kuò)展、易維護(hù)并不是一件簡單的事。這里并不強(qiáng)調(diào)一些個(gè)接口設(shè)計(jì)的原則或者設(shè)計(jì)方法,僅從如何設(shè)計(jì)一個(gè)好的接口出發(fā),簡單討論。
【資料圖】
我們寫代碼,不僅僅是為了實(shí)現(xiàn)當(dāng)前的功能,也要有利于后面的維護(hù)。所謂的維護(hù),就是代碼不僅僅是寫給自己看的,也是給別人看的。所以接口定義要清晰易懂、命名規(guī)范。
除了接口、方法、出入?yún)⒚?guī)范,也要注意代碼規(guī)范問題。一開始接觸到各種代碼壞味道的小伙伴,大多都會(huì)覺得這些規(guī)范很多余、很煩人,但實(shí)際上,這些好的編碼習(xí)慣是讓大家都能按照基本規(guī)約開發(fā),易于閱讀易于維護(hù)的基礎(chǔ)。
在接口定義時(shí),也請(qǐng)注意接口功能的單一性。其實(shí)這也是微服務(wù)的一些思想,接口功能的單一職責(zé)、明確簡單。比如登錄接口,它做的事情就是校驗(yàn)賬戶名和密碼相關(guān);訂單服務(wù)、積分服務(wù)、商品信息相關(guān)的接口都是劃分開的。
2、參數(shù)校驗(yàn)入?yún)⒊鰠⑿r?yàn)是每個(gè)程序員必備的基本素養(yǎng)。你設(shè)計(jì)的接口,必須先校驗(yàn)參數(shù)。比如入?yún)⑹欠裨试S為空、入?yún)㈤L度要求、入?yún)⑹欠裨诿杜e值范圍內(nèi)等等。日常開發(fā)中,很多低級(jí)bug都是不校驗(yàn)參數(shù)導(dǎo)致的。
提到參數(shù),就必須提到接口狀態(tài)和錯(cuò)誤碼。無論是失敗還是成功,一個(gè)完備的接口都應(yīng)該告訴調(diào)用方返回信息。如果接口失敗,具體失敗的原因是什么,這就需要定義明確的錯(cuò)誤碼和對(duì)應(yīng)描述。同時(shí),盡量對(duì)報(bào)錯(cuò)信息進(jìn)行封裝,不要直接將服務(wù)端異常信息拋出去。
3、監(jiān)控/性能如何評(píng)判一個(gè)接口的性能就必須要有監(jiān)控,這對(duì)于服務(wù)端監(jiān)視接口性能和異常報(bào)警至關(guān)重要。調(diào)用次數(shù)、可用率、TP99、TP999等監(jiān)視指標(biāo),極其重要的核心接口,還需要細(xì)分至秒級(jí)監(jiān)控加以標(biāo)識(shí)。
一個(gè)接口的性能不單單只看自己業(yè)務(wù)邏輯,外部遠(yuǎn)程調(diào)用也是消耗性能的重要部分。如果你調(diào)用第三方接口或者遠(yuǎn)程服務(wù),就需要考慮異常和超時(shí)。如果異常了,怎么處理,是重試還是當(dāng)作失敗還是告警處理。如果重試,重試幾次?這就需要站在業(yè)務(wù)角度思考這個(gè)問題。這些措施也是直接影響當(dāng)前接口性能。
提高性能的利器還可以考慮緩存。緩存用得好,可以承載更多的請(qǐng)求,提升查詢效率,減少數(shù)據(jù)庫的壓力。但是使用緩存需要考慮緩存和數(shù)據(jù)庫一致性保證、緩存擊穿等問題。
4、日志接口的關(guān)鍵代碼,要有日志的保駕護(hù)航。首先日志級(jí)別需要合理使用:error > warn > info > debug。
其次日志信息包含哪些呢,核心代碼塊調(diào)用前的入?yún)⒋蛴?、接口調(diào)用后的異常捕獲日志等。需要注意的是,如果日志中涉及比較大的JSON富文本,請(qǐng)使用log.isInfoEnable(),在高并發(fā)和復(fù)雜log信息拼接的情況下,使用這種標(biāo)準(zhǔn)的方法輸出log能夠省去不小的系統(tǒng)開銷。另外,如果構(gòu)造log信息的過程需要大量字符串操作,建議使用StringBuilder來完成字符串拼接。
5、異常/超時(shí)實(shí)現(xiàn)一個(gè)好的接口,離不開優(yōu)雅的異常處理。比如異常匹配的順序,優(yōu)先捕獲具體的異常;使用流時(shí)記得使用finally關(guān)閉流資源;
對(duì)于運(yùn)行時(shí)錯(cuò)誤,比如數(shù)據(jù)邊界越界、空指針也在日常開發(fā)中出現(xiàn),該判斷、該校驗(yàn)的還是一項(xiàng)不能少哦。
超時(shí)問題也經(jīng)常會(huì)導(dǎo)致接口不可用。設(shè)置合理的超時(shí)時(shí)間,也是在保護(hù)你的接口。超時(shí)一般與重試搭配使用,不過請(qǐng)注意,設(shè)置超時(shí)時(shí)間時(shí),需要充分考慮你的上下游設(shè)置的超時(shí)時(shí)間。比如一個(gè)請(qǐng)求率先訪問你的上游,而你的上游設(shè)置的超時(shí)時(shí)間是500ms,上游調(diào)用你的接口,但你設(shè)置的超時(shí)是2000ms,這其實(shí)就是無效超時(shí)時(shí)間。
對(duì)于接口耗時(shí)優(yōu)化,也是有一些手段的,比如遠(yuǎn)程串行改為并行調(diào)用、單次調(diào)用改為批量調(diào)用等等。但請(qǐng)注意盡量不在循環(huán)或者事務(wù)里遠(yuǎn)程調(diào)用。
6、異步接口有些場景,使用異步更合理。舉個(gè)簡單的例子,對(duì)于一些運(yùn)營操作的接口,往往需要記錄對(duì)應(yīng)操作的操作日志,記錄下是誰在什么時(shí)間操作了什么對(duì)象,便于追蹤“事發(fā)現(xiàn)場”。但是記錄操作日志并不在接口主流程上,記錄操作日志是否成功失敗也不應(yīng)該影響正常主流程的執(zhí)行,這個(gè)時(shí)候就應(yīng)該考慮用消息隊(duì)列等方式進(jìn)行異步解耦。
7、注釋可以說,注釋也是良好代碼的重要組成部分。有些人,一直相信show me the code,卻不想寫一行注釋,認(rèn)為沒有必要。但是你無法保證代碼邏輯一直清晰、高效。如果是比較復(fù)雜的話,就建議把注釋寫清楚,這對(duì)于后續(xù)維護(hù)和縷清代碼邏輯很重要。
8、降級(jí)/限流如今的請(qǐng)求調(diào)用基本都是分布式調(diào)用鏈路,當(dāng)分布式系統(tǒng)中某個(gè)基礎(chǔ)服務(wù)不可用時(shí),就會(huì)最終導(dǎo)致整個(gè)系統(tǒng)不可用,所以當(dāng)下游系統(tǒng)或者自身服務(wù)出現(xiàn)問題時(shí),一定要考慮降級(jí)。如果做的更完備的話,還可以考慮熔斷。
同時(shí),針對(duì)高并發(fā)的流量洪峰接口,必須考慮限流應(yīng)對(duì)超出系統(tǒng)的承載能力挑戰(zhàn)。限流措施也同樣可以限制爬蟲,保護(hù)系統(tǒng),丟棄多余的請(qǐng)求。
9、安全這里說的安全,范圍可太大了。比如線性安全,很多人反手上來就是HashMap,因?yàn)樗欠蔷€性安全的,可以考慮高并發(fā)下的ConcurrentHashMap。
如果前端重復(fù)請(qǐng)求,你的邏輯如何處理?是不是考慮接口去重處理(有時(shí)候是防刷處理)。簡單點(diǎn),可以使用redis防重處理,同樣的請(qǐng)求,一定時(shí)間間隔內(nèi)進(jìn)行過濾。當(dāng)然,對(duì)于一些并發(fā)不高的接口,比如轉(zhuǎn)賬類接口,推薦使用數(shù)據(jù)庫主鍵或者唯一索引。
如果消息隊(duì)列出現(xiàn)重復(fù)消費(fèi)的情況,你的業(yè)務(wù)邏輯怎么控制?是不是考慮冪等性校驗(yàn)。
防重主要為了避免產(chǎn)生重復(fù)數(shù)據(jù),把重復(fù)請(qǐng)求攔截下來即可。而冪等設(shè)計(jì)除了攔截已經(jīng)處理的請(qǐng)求,還要求每次相同的請(qǐng)求都返回一樣的結(jié)果。不過很多時(shí)候,它們的處理流程和方式是類似的。
還有一些其他安全方面的考慮,比如讀寫分離、代碼鎖的粒度控制、數(shù)據(jù)加密等等。
10、溝通為什么要有溝通?又為什么把溝通放在最后呢?遇到一些技術(shù)難題,跟技術(shù)leader對(duì)齊方案。實(shí)現(xiàn)需求的過程中,有什么問題,需要及時(shí)跟產(chǎn)品溝通。需要跟客戶端對(duì)齊接口,一定不能上來就自己埋頭把接口定義完了。種種場景,學(xué)會(huì)溝通是非常重要的,有效、高效溝通不僅會(huì)帶來愉悅心情,開發(fā)起來很順暢,也會(huì)提高人際關(guān)系。
好啦,以上就是根據(jù)自身經(jīng)驗(yàn),對(duì)“如何設(shè)計(jì)一個(gè)接口?”問題的小小回答,如有不足,敬請(qǐng)指教。
作者:京東零售 李澤陽
來源:京東云開發(fā)者社區(qū) 轉(zhuǎn)載請(qǐng)注明來源
關(guān)鍵詞:

營業(yè)執(zhí)照公示信息