<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          萬萬沒想到,這都能發(fā)現(xiàn) Bug?!

          共 1897字,需瀏覽 4分鐘

           ·

          2021-12-17 10:55

          Bug 總會不約而至

          大家好,我是魚皮,昨天工作中遇到一個挺好玩兒的小 Bug,和大家分享下,小白可懂~

          事情是這樣的,為了保證發(fā)到線上的項目代碼能正常運行,每次構(gòu)建發(fā)布前,我們都會執(zhí)行一遍單元測試,對業(yè)務(wù)流程、一些增刪改查之類的代碼片段進(jìn)行驗證。

          以前我上線項目都是有節(jié)奏有規(guī)劃的,也沒注意跑一遍單元測試要花多長時間,反正慢點我就先去干別的事兒。直到昨天,我急著修復(fù)一個線上 Bug,結(jié)果發(fā)現(xiàn)單元測試竟然特么跑了近 20 分鐘,直接給我整不會了。

          雖說隨著項目功能的不斷增多,測試用例也越來越多,是會比以前多花一點時間。但整個測試數(shù)據(jù)庫量級都不過千,怎么會這么慢呢?

          于是,我又執(zhí)行了一遍所有測試用例,觀察各用例的耗時,結(jié)果發(fā)現(xiàn)有一個簡單的查詢接口竟然執(zhí)行了近 10 分鐘。

          由于不能透露真實的業(yè)務(wù)場景,給大家打個比方,這個接口的作用大概就是查詢某用戶信息以及他關(guān)聯(lián)的所有資產(chǎn)詳情列表,每個資產(chǎn)詳情都要查幾個不同的表才能得到完整數(shù)據(jù),相對比較耗時。

          用一段偽代碼來描述,大概是這樣的:

          //?耗時?0.1?秒
          let?user?=?getUser();
          //?循環(huán)
          for(id?in?user.assetIds)?{
          ??//?耗時?0.1?秒
          ??let?asset?=?getDetail();
          ??//?耗時?0.1?秒
          ??asset.xx?=?getXX();
          ??//?耗時?0.1?秒
          ??asset.yy?=?getYY();
          ??//?耗時?0.1?秒
          ??asset.zz?=?getZZ();
          }

          可以看出,如果該用戶有很多資產(chǎn)的話,查詢耗時將線性增加。

          那肯定有同學(xué)要吐槽了:為啥是查詢所有,而不是分頁一批一批去查呢?這個就得從實際的業(yè)務(wù)場景去考慮了。我們系統(tǒng)情況是:用戶一般不會有太多資產(chǎn)詳情的,而且要把數(shù)據(jù)全部返回給前端展示,所以不分頁會更方便些。

          但萬萬沒想到啊,每次測試插入資產(chǎn)的方法時,我都指定了該資產(chǎn)的所屬用戶 id = 1!日積月累,最終導(dǎo)致該用戶名下的資產(chǎn)數(shù)多達(dá)近千個!然后又恰好,我測試該查詢接口時,查的就是用戶 id = 1 的數(shù)據(jù),就導(dǎo)致了悲劇的發(fā)生。

          解決方案也很簡單,把順序查詢轉(zhuǎn)為并發(fā)查詢即可。

          具體的步驟就是開一個線程池,然后 Java 的話可以用 CompletableFuture 類來創(chuàng)建并發(fā)查詢?nèi)蝿?wù),每個任務(wù)負(fù)責(zé)查詢一個資產(chǎn)的詳情,最后等所有資產(chǎn)詳情都查詢好,再整體返回。

          Java 代碼大概是這樣的(不保證能運行):

          //?開個線程池,取任務(wù)執(zhí)行
          ExecutorService?executor?=?new?ThreadPoolExecutor(
          ??8,?100,?5,
          ??TimeUnit.MINUTES,
          ??new?ArrayBlockingQueue<>(10000)
          );
          //?任務(wù)列表
          List>?fList?=?new?ArrayList<>();
          for?(int?id?:?assetIds)?{
          ??//?創(chuàng)建任務(wù)
          ??CompletableFuture?f?=?CompletableFuture.supplyAsync(
          ????()?->?{
          ??????Asset?asset?=?getDetail();
          ??????asset.xx?=?getXX();
          ??????asset.yy?=?getYY();
          ??????asset.zz?=?getZZ();
          ?????return?asset;
          ???},
          ????executor
          ??);
          ??fList.add(f);
          }
          //?阻塞,等待所有任務(wù)執(zhí)行完成
          List?CompletableFuture
          ??.allOf(fList.toArray(new?CompletableFuture[0]))
          ??.get();

          唉,本來是想著就幾條數(shù)據(jù)沒必要用并發(fā)查詢的,沒想到還是潛移默化間影響了自己開發(fā)上線項目的效率。

          不過,這次的小事件也再次說明了單元測試的重要性,這玩意不僅能測出程序不能正常運行的問題,還能側(cè)面反映出你系統(tǒng)上存在的風(fēng)險和缺陷。所以,大家做項目時還是不能偷懶,要好好寫單元測試哈!



          以上就是本期分享,有幫助的話還請給魚皮一個 點贊 + 在看 ,謝謝大家!

          往期推薦

          Log4j,炸了?。?!

          這款內(nèi)網(wǎng)穿透神器,免費!

          做免費網(wǎng)站1年,要花多少錢?

          我把學(xué)習(xí)路線都開源了!

          我有一臺服務(wù)器,能干啥?

          瀏覽 57
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  91麻豆精产国品一二三产品测评 | 婷婷色五月天丁香 | 强欧美小嫩苞第一次免费视频 | 97啪啪| 爱爱无码免费视频 |