中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

贛州章貢區(qū)房價(jià)google優(yōu)化排名

贛州章貢區(qū)房價(jià),google優(yōu)化排名,廣東建設(shè)繼續(xù)教育網(wǎng)站首頁,濟(jì)南的企業(yè)網(wǎng)站目錄 一. 現(xiàn)狀問題 二. 分析原因 三. 采取措施 四. 實(shí)踐步驟 五. 效能提升 資料獲取方法 一. 現(xiàn)狀問題 針對現(xiàn)如今高并發(fā)場景的業(yè)務(wù)系統(tǒng),“并發(fā)問題” 終歸是必不可少的一類(占比接近10%),每次出現(xiàn)問題和事故后&#xff0c…

目錄

一. 現(xiàn)狀·問題

二. 分析原因

三. 采取措施

四. 實(shí)踐步驟

五. 效能提升

資料獲取方法


一. 現(xiàn)狀·問題

針對現(xiàn)如今高并發(fā)場景的業(yè)務(wù)系統(tǒng),“并發(fā)問題” 終歸是必不可少的一類(占比接近10%),每次出現(xiàn)問題和事故后,需要耗費(fèi)大量人力成本排查分析并修復(fù)。那如果能在事前盡可能避免豈不是很香?

二. 分析原因

  • 當(dāng)前并發(fā)測試多數(shù)依賴測試人員進(jìn)行腳本測試,同時(shí)還依賴了研發(fā)和產(chǎn)品識別出并發(fā)操作的場景用例。
  • 對于并發(fā)測試,大概兩條路子:
  1. 所有修改同樣數(shù)據(jù)的命令式接口都測一遍?【耗費(fèi)巨大測試成本】
  2. 保證黃金流程的接口,研發(fā)從頭扒代碼?!究赡軙?huì)遺漏,耗費(fèi)一定研發(fā)成本】

🤔自我反思

  • 作為研發(fā),是不是在剛開發(fā)接口時(shí)候,識別到并發(fā)場景隨著單元測試階段同時(shí)進(jìn)行并發(fā)測試,這樣的成本是最小的,收益是最高效的!

三. 采取措施

并發(fā)測試前置

采用CI持續(xù)集成機(jī)制,依靠行云流水線,底層利用junit5單元測試框架并發(fā)parallel引擎,嵌入同步數(shù)據(jù)庫的自定義unit test腳本,將每個(gè)并發(fā)case維護(hù)成單元測試,數(shù)據(jù)自我閉環(huán),可重復(fù)執(zhí)行

將核心的并發(fā)場景進(jìn)行及時(shí)的運(yùn)行驗(yàn)證,最早洞察,最早驗(yàn)證,最小成本,最大保障!

四. 實(shí)踐步驟

前提:配置junit-platform.properties

# src/test/resources/junit-platform.properties
junit.jupiter.execution.parallel.enabled=true
junit.jupiter.execution.parallel.config.strategy=fixed
junit.jupiter.execution.parallel.config.fixed.parallelism=20

單接口并發(fā)-@RepeatedTest

  • ManualCheckAppConcurrentTest 出庫復(fù)核并發(fā)測試「單接口并發(fā)」-> 手動(dòng)復(fù)核 10個(gè)線程

👉 核心代碼塊

public class ManualCheckAppConcurrentTest extends ConcurrentTest {@ResourceManualCheckAppService manualCheckAppService;//記錄執(zhí)行成功的線程數(shù)static int successThreadCount = 0;///// 單接口并發(fā)///@DisplayName("(單接口并發(fā))并發(fā)測試【手動(dòng)確認(rèn)復(fù)核】")@Description("(10個(gè)線程)場景:復(fù)核1件,一共5件,應(yīng)該有5個(gè)線程成功,5個(gè)線程失敗:沒有查詢到容器明細(xì)記錄" +"使用友好式分布式鎖防止并發(fā),并發(fā)后等待重試,保證順序執(zhí)行無異常!")@Execution(CONCURRENT)@RepeatedTest(value = 10, name = "{displayName}:{totalRepetitions}-{currentRepetition}")public void testConfirmChecked(TestInfo testInfo) {manualCheckAppService.confirmChecked(mockConfirmCheckedDto());successThreadCount++;}/*** 斷言最終結(jié)果:數(shù)據(jù)無問題,線程執(zhí)行無問題*/@AfterAllpublic static void assertResult() {//線程執(zhí)行成功數(shù)期望:一共5件,每個(gè)線程復(fù)核1件,共有5個(gè)線程成功Assertions.assertEquals(5, successThreadCount);//數(shù)據(jù)成功期望:沒有待復(fù)核的容器明細(xì)了,因?yàn)槎紡?fù)核成功了,一共5件ConfirmCheckedDto confirmCheckedDto = mockConfirmCheckedDto();List<ContainerDetailPo> containerDetailPos = SpringUtil.getBean(ContainerDetailDao.class).selectUncheckDetailsBySoAndSku(confirmCheckedDto.getTaskNo(), confirmCheckedDto.getShipmentOrderNo(), confirmCheckedDto.getSku(), confirmCheckedDto.getWarehouseNo());Assertions.assertTrue(CollectionUtils.isEmpty(containerDetailPos));}@Test@Sql({"/concurrent/manualCheck.sql"})@Overridevoid prepareData()

多場景并發(fā)-@Execution(CONCURRENT)

  • CheckAppConcurrentTest 出庫復(fù)核并發(fā)測試「多場景并發(fā)」-> 手動(dòng)復(fù)核|自動(dòng)復(fù)核

👉 核心代碼塊

public class CheckAppConcurrentTest extends ConcurrentTest {@ResourceManualCheckAppService manualCheckAppService;@ResourceAutoCheckAppService autoCheckAppService;///// 多場景并發(fā)///@DisplayName("(多場景并發(fā))并發(fā)測試【自動(dòng)確認(rèn)復(fù)核】")@Description("與手動(dòng)復(fù)核發(fā)生并發(fā)場景,期望可能存在業(yè)務(wù)異常(自定義鎖沖突發(fā)生的消息)")@Execution(CONCURRENT)@Testpublic void testAutoCheckBySo() {autoCheckAppService.autoCheckBySo(Lists.newArrayList("SO-6_6_601-1492066800186167296"), mockAutoCheckBySoDto());}@DisplayName("(多場景并發(fā))并發(fā)測試【手動(dòng)確認(rèn)復(fù)核】")@Description("與自動(dòng)復(fù)核發(fā)生并發(fā)場景,期望可能存在業(yè)務(wù)異常(自定義鎖沖突發(fā)生的消息)")@Execution(CONCURRENT)@Testpublic void testConfirmChecked() {manualCheckAppService.confirmChecked(mockConfirmCheckedDto());}/*** 斷言最終結(jié)果:數(shù)據(jù)無問題*/@AfterAllpublic static void assertResult() {//數(shù)據(jù)成功期望:沒有待復(fù)核的容器明細(xì)了,無論是手動(dòng)復(fù)核還是自動(dòng)復(fù)核,都會(huì)全部復(fù)核完ConfirmCheckedDto confirmCheckedDto = mockConfirmCheckedDto();List<ContainerDetailPo> containerDetailPos = SpringUtil.getBean(ContainerDetailDao.class).selectUncheckDetailsBySoAndSku(confirmCheckedDto.getTaskNo(), confirmCheckedDto.getShipmentOrderNo(), confirmCheckedDto.getSku(), confirmCheckedDto.getWarehouseNo());Assertions.assertTrue(CollectionUtils.isEmpty(containerDetailPos));}@Test@Sql({"/concurrent/manualCheck.sql"})@Overridevoid prepareData() {}

并發(fā)單測基類-@Transactional

ConcurrentTest?建議抽出并發(fā)測試基類(主要目的:準(zhǔn)備數(shù)據(jù)、設(shè)置路由、數(shù)據(jù)清除、獨(dú)立執(zhí)行)

@Tag("parallel")分組: 并發(fā)測試用例,有助于單獨(dú)執(zhí)行套件! ?

👉 核心代碼塊


@SpringBootTest(classes = WebApplication.class)
@Tag("parallel")
public abstract class ConcurrentTest {/*** 并發(fā)測試場景的前提數(shù)據(jù)準(zhǔn)備* { @Sql 數(shù)據(jù)腳本配置 }*/@Transactional@Order(0)@Rollback(false)abstract void prepareData();/*** 設(shè)置當(dāng)前線程數(shù)據(jù)源*/@BeforeTransactionpublic void setThreadDataSource() {DataSourceContextHolder.clearDataSourceKey();//多數(shù)據(jù)源,分庫分表DataSourceContextHolder.setDataSource("ds0");}/*** 清除數(shù)據(jù)*/@Rollback(false)@AfterAllpublic static void clearData(){new DatabaseSyncTest().execute("wms_check","wms_check_test");}

數(shù)據(jù)準(zhǔn)備-@Sql

如何準(zhǔn)備數(shù)據(jù)?

=> 新建一個(gè)專門單元測試/并發(fā)測試的空數(shù)據(jù)庫

準(zhǔn)備測試場景的前置數(shù)據(jù)SQL腳本

👉 源腳本

DELETE FROM ck_task;
INSERT INTO ck_task (id, task_no, sku_qty, total_qty, platform_no, status, warehouse_no, create_user,update_user, create_time, update_time, ts, deleted, suggest_platform, uuid,parent_task_no, pick_differ_allow, operation_type, picking_flag, task_type,ext_info,subtask_qty, tenant_code, current_stream_no, confluence, batch_no, requirements)
VALUES (1492071049884340224, 'T6X6X60122021100000329', 1.0000, 5.0000, '', 0, '6_6_601', 'xiaoyan', 'xiaoyan','2022-02-11 17:45:26', '2022-02-11 17:45:26', '2022-02-11 17:45:26', 0, '', 'zyr1228003', '', 0, 0, 0, 0, null,null, 'TC30020150', 0, 1, 'cj006001', '{"allowBatchCheck": true}');     

數(shù)據(jù)回滾-@ParameterizedTest

CI自動(dòng)同步數(shù)據(jù)庫表結(jié)構(gòu):?測試環(huán)境數(shù)據(jù)庫->單測數(shù)據(jù)庫

利好:(研發(fā)無需被動(dòng)維護(hù)schema,自動(dòng)與真實(shí)數(shù)據(jù)庫結(jié)構(gòu)同步)

只需要將下面單測copy到代碼中,將fromDb和toDb參數(shù)修改成自己數(shù)據(jù)庫即可!

👉 源代碼

    @DisplayName("單元測試MYSQL-DB結(jié)構(gòu)同步")@SneakyThrows@ParameterizedTest@CsvSource("wms_check,wms_check_test")public void execute(String fromDb, String toDb) {ResultSet resultSet = null;Class.forName("com.mysql.jdbc.Driver");try (Connection connection = DriverManager.getConnection("***","user", "***");Statement statement = connection.createStatement()) {String initDb = "DROP DATABASE IF EXISTS " + toDb + ";CREATE DATABASE " + toDb + ";";log.info(initDb);statement.executeUpdate(initDb);resultSet = statement.executeQuery("SHOW TABLES FROM " + fromDb + ";");List<String> tableNames = Lists.newArrayList();while (resultSet.next()) {tableNames.add(resultSet.getString("Tables_in_" + fromDb));}for (String tableName : tableNames) {String syncSql = "DROP TABLE IF EXISTS " + toDb + "." + tableName + ";" +"CREATE TABLE " + toDb + "." + tableName + " LIKE " + fromDb + "." + tableName + ";";log.info(syncSql);statement.executeUpdate(syncSql);}} finally {if(resultSet != null){resultSet.close();}}}

配置CI-@行云流水線

建議在提測流水線增加,不要再日常dev流水線(集成測試相對耗時(shí))

只執(zhí)行并發(fā)單測用例-Dtest.mode 基于junit5 @Tag

JUnit 5 User Guide

mvn test -Dtest.mode=parallel

配置IDEA-本地測試

—— 只運(yùn)行并發(fā)測試用例

執(zhí)行結(jié)果

單接口并發(fā)單測

多場景并發(fā)單測

五. 效能提升

5.1需求交付效率提升

5.1.1降低測試周期階段時(shí)長

2022-02月實(shí)踐后

因?yàn)椤覆l(fā)測試」前置到「研發(fā)單元測試」環(huán)節(jié),所以「測試階段」時(shí)長縮短 (2.5 天 -> 1 天)

2022-Q1

2022-Q2

2022-Q3

2022-Q4

「測試周期」階段停留時(shí)長和占比,呈下降趨勢!

5.1.2縮短需求交付全周期

2022-02月實(shí)踐后

因?yàn)椤笢y試周期」縮短,研發(fā)單元測試成本幾乎不變,所以「需求交付全周期」隨之縮短(55 天 -> 35 天)!

5.2人效提升

5.2.1提升驗(yàn)證全面性

「case by case」 ,通過單元測試「斷言機(jī)制」,最細(xì)粒度全方位驗(yàn)證!

在【開發(fā)階段】識別到接口存在并發(fā)問題,及時(shí)編寫單元測試進(jìn)行驗(yàn)證,針對分布式鎖和樂觀鎖等常用防并發(fā)手段,對應(yīng)不同的assert方式:

  • 數(shù)據(jù)庫樂觀鎖:通過判斷最終數(shù)據(jù)保證執(zhí)行無問題
  • 分布式友好鎖:不會(huì)報(bào)錯(cuò),會(huì)等待,最終所有請求處理成功
  • 分布式?jīng)_突鎖:直接報(bào)錯(cuò),斷言異常信息
  • ......

5.2.2降低測試人力成本

減少花大量時(shí)間專項(xiàng)測試N個(gè)接口并發(fā)測試成本,「最早發(fā)現(xiàn),最早處理,最小成本」!

根據(jù)下圖可見,從編碼階段、單元測試階段、接口測試階段、集成測試階段、預(yù)發(fā)布階段等軟件生命周期中,越早發(fā)現(xiàn)問題,付出成本越小。

5.2.3提升需求吞吐量

2022-02月實(shí)踐后

因?yàn)闇p少人力成本,所以會(huì)直接提升需求的吞吐量(200個(gè) -> 225個(gè))!

5.3過程質(zhì)量提升

5.3.1降低問題的發(fā)生概率

「并發(fā)測試前置」 到研發(fā)單元測試環(huán)節(jié),可減少缺陷數(shù),降低問題發(fā)生概率!

5.3.2減少線上問題數(shù)

👉 今年線上問題-并發(fā)問題 類別為 0

5.3.2減少Bug數(shù)

👉過程質(zhì)量中并發(fā)問題趨勢逐步降低


資料獲取方法

【留言777】

各位想獲取源碼等教程資料的朋友請點(diǎn)贊 + 評論 + 收藏,三連!

三連之后我會(huì)在評論區(qū)挨個(gè)私信發(fā)給你們~

http://www.risenshineclean.com/news/42062.html

相關(guān)文章:

  • 鎮(zhèn)江網(wǎng)站建設(shè)策劃被公司優(yōu)化掉是什么意思
  • 做網(wǎng)站需要哪些資料百度廣告客服電話
  • 怎么用wordpress做網(wǎng)站seo專員工資一般多少
  • 百度云網(wǎng)站建設(shè)教程視頻域名seo站長工具
  • 縣城購物網(wǎng)站網(wǎng)絡(luò)營銷策略主要包括
  • 怎樣設(shè)計(jì)靜態(tài)網(wǎng)站頁面谷歌官方app下載
  • 獨(dú)立電商網(wǎng)站seo建站流程新手搭建網(wǎng)站第一步
  • 上海徐匯做網(wǎng)站寧波公司做網(wǎng)站
  • 梅河口做網(wǎng)站在百度做廣告多少錢
  • 哪里可以學(xué)酷家樂設(shè)計(jì)seo數(shù)據(jù)優(yōu)化
  • wordpress pingaso優(yōu)化平臺
  • 網(wǎng)站開發(fā)計(jì)入什么費(fèi)用企點(diǎn)qq
  • 淘寶的網(wǎng)站建設(shè)品牌推廣手段
  • 做查詢新生寢室的網(wǎng)站外貿(mào)網(wǎng)絡(luò)推廣怎么做
  • 建設(shè)證件查詢官方網(wǎng)站長春頭條新聞今天
  • 做大數(shù)據(jù)和網(wǎng)站開發(fā)的前景seo網(wǎng)絡(luò)優(yōu)化推廣
  • wordpress 目錄 導(dǎo)航站青島 google seo
  • 課程網(wǎng)站建設(shè)的設(shè)計(jì)報(bào)告google seo 優(yōu)化教程
  • 無錫網(wǎng)絡(luò)營銷推廣軟件蘭州seo
  • 網(wǎng)站加載慢圖片做延時(shí)加載有用百度關(guān)鍵詞怎么設(shè)置
  • 哪家專門做特賣的網(wǎng)站?杭州seo整站優(yōu)化
  • 網(wǎng)站做百度競價(jià)利于百度優(yōu)化aso應(yīng)用商店優(yōu)化原因
  • 西安網(wǎng)站建設(shè)公司排名seo百度刷排名
  • 做網(wǎng)站需要公司資料嗎關(guān)鍵詞優(yōu)化排名軟件s
  • 模板做的網(wǎng)站不好優(yōu)化北京關(guān)鍵詞seo
  • 美國做空機(jī)構(gòu)渾水網(wǎng)站百度營銷推廣官網(wǎng)
  • 北京網(wǎng)站設(shè)計(jì)公司有哪些摘抄一篇新聞
  • 大連開發(fā)區(qū)網(wǎng)站制作建設(shè)公司游戲推廣合作
  • 網(wǎng)站建設(shè)產(chǎn)品圖片尺寸要求百度貼吧網(wǎng)頁版
  • 德陽城鄉(xiāng)建設(shè)部網(wǎng)站首頁網(wǎng)站創(chuàng)建