天天看點

封裝複雜度之批量接口一、背景

一、背景

在平時項目開發過程中,難免需要作為接口提供方封裝批量接口給上遊調用;或者作為上遊系統調用下遊業務或者中間件的批量接口,執行某些操作。

封裝複雜度之批量接口一、背景

常見的批量操作有很多,比如批量查詢内容詳情,批量發送提醒;批量插入資料、批量更新、批量發送MQ消息等。

不知道,大家想過沒有。

為什麼要提供批量接口?

作為批量接口的提供方和批量接口的使用方我們通常需要注意哪些問題?

二、 問題思考

2.1 為什麼要提供批量接口?

通常最主要的一個原因是為了性能優化。

通常 IO 操作是性能的主要瓶頸,批量接口可以減少網絡 IO 次數,進而達到降低耗時的目的。

2.2 批量接口的提供方我們要注意哪些問題?

【1】健壯性

很多人,尤其是新手,容易直線思考,批量接口嘛,直接傳給我一個 List 作為參數,傳回結果即可。

(1) 批量限制

如果上遊傳入集合中元素多,會不會有問題?

上遊傳入的元素過多,很容易對本系統造成很多壓力,而且非常容易逾時。

public List queryOrders(String userId, List orderIds){

 // 省略

}

是以,批量接口通常需要增加分頁參數,通常需要對集合長度進行檢查。

public List queryOrders(String userId, List orderIds, PageRequest page){

 // orderIds size 檢查

FBI Warning:請在函數的注釋中或者接口文檔中必須顯式标注集合長度限制!

(2)參數校驗

上遊傳入的參數合法性也要進行校驗,比如例子中 userId 是否有權限檢視這些 order ?

 // userId 合法性校驗

再比如傳入日期,日期的格式是否正确,是否符合預期? 都是需要考量的事情。

(3)并發校驗

有些批量操作不允許并發,要考慮加分布式鎖。

(4)失敗處理

失敗該如何處理,也是一個需要考慮的問題

将失敗的對象當做傳回值傳回給上遊? 将失敗的部分忽略掉?中間有資料失敗,需要復原?

【2】可拓展性

通常建議将主要參數甚至傳回值定義成自定義對象,而不是使用封裝類型在函數簽名中鋪開。

請看下面的案例,如果後續需要新增一些參數,就需要提供新的接口:

可以參考以下寫法,将參數定義為批量查詢對象:

public List queryOrders(OrderBatchQuery query, PageRequest page){

這樣如果需要新增參數時,不需要修改函數簽名。

對于一些“寫”操作,還可以考慮,提供失敗處理政策,如失敗抛異常、部分失敗傳回失敗清單等。

【3】封裝複雜度

通常提供批量接口的同學會理直氣壯的認為,設定集合 size 限制,最多再給個 page 參數就可以了。

如果有批量的需求,自己去對集合進行分批,自己對分頁進行處理呗!

其實最大的問題是,幾乎所有上遊都需要對目前自己拿到的整個 list 的所有内容都要進行查詢!!每個使用方都要自己處理分批和分頁,非常麻煩,氣得直跺腳!!!

其實有時候可以多走一步,既能展現出自己的專業度,也能更容易赢得上遊的信任和稱贊。

可以考慮提供一個自動分批和處理分頁的方法(需告知上遊雖然可以自動分批,但是如果 size 過大仍然會有因資料量過大導緻調用逾時,甚至 OOM 的風險)。

還可以提供一個自動對參數接口進行分批執行調用拼接結果的工具類等。

對于帶傳回值的調用,可以參考下面工具方法的定義:

public static List partitionCall2ListAsync(List dataList,

                                                        int size,

                                                        ExecutorService executorService,

                                                    Function, List> function) {

其中 dataList 即待分批的集合, size 即每一批的數量, executorService 線程池,Function function 即單次調用。

可參考為的另外一篇博文:

https://blog.csdn.net/w605283073/article/details/101399427

2.3 批量接口的使用方需要主要哪些問題?

【1】長度限制

不管是業務接口還是中間件的批量接口,通常參數中集合都會有 size 限制,一定仔細看函數說明、接口文檔,甚至有條件拉下對方源碼看看實作方式。

工作這幾年,已經見到過身邊同時多次因為使用下遊提供的批量接口,而下遊沒有在接口上寫 size 限制,導緻上遊在資料量大時報錯,測試階段通常資料量較小不容易發現該問題。

如果下遊沒有提供自動分批的批量調用方法,可以自己在本系統的外部依賴子產品通過編寫一個 XXX對應的 XXXXClient 進行二次封裝,避免将複雜度再向上遊暴露。

【2】 部分失敗如何處理?

要核實下遊對部分失敗的情況的處理辦法,是提供了失敗政策,還是一起復原,我們直接失敗或者重試?

三、啟發

本文希望通過批量接口的編寫和使用,讓大家意識到封裝複雜性的必要性。

希望大家在設計方案或編寫代碼時,一定要帶着“封裝複雜度”的思想,盡量将複雜度封裝在更底層的位置。

這也是“迪米特法則”即“最小知道原則”的要求,也是高内聚、低耦合的要求。

創作不易,如果你覺得本文對你有幫助,歡迎點贊、收藏加關注,你的支援和鼓勵是我創作的最大動力

————————————————

版權聲明:本文為CSDN部落客「明明如月學長」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。

原文連結:

https://blog.csdn.net/w605283073/article/details/120575996