1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        萬萬沒想到,這都能發(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
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            日日摸夜夜骑 | 精品国产乱码久久久久久蜜坠欲下 | 免费看又色又爽又黄的成人用品 | 久久日韩乱码一二三四区别 | 黄色小电影网址 | 久久性爰视频 | 天天弄一弄天天日一日天天射一射 | 无码AV电影在线 | www.黄色 | 国产欧美精品国产国产专区 |