【工作实践(多线程)】十个线程任务生成720w测试数据对系统进行性能测试

简介: 【工作实践(多线程)】十个线程任务生成720w测试数据对系统进行性能测试

起因

  1. 公司最近有个客户需要把2-3w台设备各类数据存放到我们平台,这么多设备带来的数据量一年下来单表大概会达到720w,这样会使得平台某些分页查询或相关业务效率变慢。所以想让客户自己去阿里云买服务器,但是客户不想管理,想丢在我们平台。那也没办法,客户是上帝,能做是能做,不过得加钱!!! 哈哈哈
  2. 要帮客户存储数据,那得知道买多大的服务器合适,或者租多大服务器,一年得多少钱,这个得有一定的评估。所以就得生成一年的数据量了,进行存储和效率测试,系统后台的性能调优。

思路

  1. 要生成720w数据得有基础的2w台设备基础信息,所以现同普通方式生成了2w基础数据
  2. 720w = 2w * 360 每个表一天一笔数据,一年按照360算,一共720w
  3. 数据量有这么大,于是我 Ctrl+Alt+Del 打开任务管理器,看了看电脑的配置,评估一下CPU能扛得住怎样的摩擦,发现6核12处理器
  4. 那就给他来十个线程,每个线程处理2000基础数据生成72w,应该可以生成出来。

实践

1.新建定时器

@Slf4j
@Configuration
@EnableScheduling
public class InsertBatchMeterArchiveTask implements SchedulingConfigurer {
    @Autowired
    private MeterArchiveService meterArchiveService;
    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.addTriggerTask(() -> {
            try {
                meterArchiveService.insertBatchBaseInfo();
            } catch (Exception e) {
                log.error("insertBatchBaseInfo meter error:{}", e.getMessage());
            }
        }, triggerContext -> {
            String cron = "0 37 12 * * ? "; 
            return new CronTrigger(cron).nextExecutionTime(triggerContext);
        });
    }
}
   
  1. 业务实现
public static List<Date> dateList = new ArrayList<>(360);
@Override
    public void insertBatchBaseInfo() throws InterruptedException {
        for (int i = 0; i < 360; i++) {
            Calendar instance = Calendar.getInstance();
            instance.setTime(CommonUtil.getCurrentDate());
            instance.add(Calendar.DAY_OF_YEAR, -i);
            dateList.add(instance.getTime());
        }
        // id 20062 --> 40061
        System.out.println(System.currentTimeMillis());
        List<MeterArchiveDO> meterArchiveDOS = meterArchiveMapper.selectList(new QueryWrapper<MeterArchiveDO>()
                .eq("area_id", 9).gt("id", 100));
        int listSize = meterArchiveDOS.size();
        int toIndex = 2000;
        //用map存起来新的分组后数据
        Map<String, List<MeterArchiveDO>> map = new HashMap();
        int keyToken = 0;
        for (int i = 0; i < meterArchiveDOS.size(); i += 2000) {
            //作用为toIndex最后没有2000条数据则剩余几条newList中就装几条
            toIndex = (i + 2000 > listSize ? listSize - i : toIndex);
            List newList = meterArchiveDOS.subList(i, i + toIndex);
            map.put("keyName" + keyToken, newList);
            keyToken++;
        }
        System.out.println(System.currentTimeMillis());
        // 处理生成数据
        dealGenerateData(map);
    }
  • 这里之前发生了线程不安全问题
    原因是在线程实现里面用到了Calendar进行时间处理,导致时间错乱,因为Calendar是单例的,每个线程任务都使用了这个变化的时间。所以通过声明全局变量,把360天都生成出来,传到线程处理业务中,就不会有这种情况了。
  1. 处理生成数据
/**
     * 处理生成数据
     *
     * @param map
     */
    private void dealGenerateData(Map map) throws InterruptedException {
        //线程池10个线程
        ExecutorService executorService = Executors.newFixedThreadPool(10);
        //第一批十个任务
        List<StartAgent> agentsStart = new ArrayList();
        for (int i = 0; i < 10; i++) {
            agentsStart.add(new StartAgent((List<MeterArchiveDO>) map.get("keyName" + i), meterDayFlowWaterMapper,dateList));
        }
        List<List<StartAgent>> task = new ArrayList<>();
        task.add(agentsStart);
        //记录任务执行时间
        long t1 = System.currentTimeMillis();
        CountDownLatch c;
        //循环任务组
        for (List<StartAgent> startList : task) {
            //定义线程阻塞为10
            c = new CountDownLatch(11);
            for (StartAgent agent : startList) {
                agent.setCountDownLatch(c);
                executorService.submit(agent);
            }
            c.await();
        }
        executorService.shutdown();
    }
  1. 具体线程内业务实现
@Data
public class StartAgent implements Runnable {
    private CountDownLatch countDownLatch;
    private List<MeterArchiveDO> meterArchiveDOS;
    private MeterDayFlowWaterMapper meterDayFlowWaterMapper;
    private List<Date> dateList;
    public StartAgent(List<MeterArchiveDO> meterArchiveDOS, MeterDayFlowWaterMapper meterDayFlowWaterMapper, List<Date> dateList) {
        this.meterArchiveDOS = meterArchiveDOS;
        this.meterDayFlowWaterMapper = meterDayFlowWaterMapper;
        this.dateList = dateList;
    }
    @Override
    public void run() {
        try {
            System.out.println("开始启动节点:" + Thread.currentThread().getName());
            MeterDayFlowWaterDO meterDayFlowWaterDO = new MeterDayFlowWaterDO();
            for (MeterArchiveDO meterArchiveDO : meterArchiveDOS) {
                for (int i = 0; i < 360; i++) {
                    BeanUtils.copyProperties(meterArchiveDO, meterDayFlowWaterDO);
                    meterDayFlowWaterDO.setMeterReadTime(dateList.get(i));
                    meterDayFlowWaterDO.setMeterSaveTime(dateList.get(i));
                    meterDayFlowWaterDO.setMeterPositiveFlow("6.66");
                    meterDayFlowWaterDO.setMeterReverseFlow("0.05");
                    meterDayFlowWaterDO.setMeterIncrementFlow("1.38");
                    meterDayFlowWaterDO.setSync(1);
                    meterDayFlowWaterDO.setRemainingAmount("100");
                    meterDayFlowWaterMapper.insert(meterDayFlowWaterDO);
                }
            }
            System.out.println(Thread.currentThread().getName() + "执行完毕");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //注意一定要在finally调用countDown,否则产生异常导致没调用到countDown造成程序死锁
            countDownLatch.countDown();
        }
    }
    public void setCountDownLatch(CountDownLatch countDownLatch) {
        this.countDownLatch = countDownLatch;
    }
}

测试

欢迎大佬指点探讨!!!

相关文章
|
8月前
|
安全 数据管理 测试技术
告别蛮力:让测试数据生成变得智能而高效
告别蛮力:让测试数据生成变得智能而高效
672 120
|
数据采集 算法 数据管理
频标频稳比对测试系统重新定义测量边界
在上海张江实验室的超净间里,一束激光正以每秒 30 万公里的速度穿越真空腔,与原子跃迁频率进行着纳米级的较量。而在千里之外的西安高新区,一台黑色金属机箱内,SYN5609A 型频标比对测量系统正以同样的精度,为这场量子级的时间竞赛提供着基准坐标。这台看似普通的仪器,正在用双混频时差技术,将人类对时间的掌控精度推向新的维度。
|
9月前
|
机器学习/深度学习 人工智能 测试技术
EdgeMark:嵌入式人工智能工具的自动化与基准测试系统——论文阅读
EdgeMark是一个面向嵌入式AI的自动化部署与基准测试系统,支持TensorFlow Lite Micro、Edge Impulse等主流工具,通过模块化架构实现模型生成、优化、转换与部署全流程自动化,并提供跨平台性能对比,助力开发者在资源受限设备上高效选择与部署AI模型。
785 9
EdgeMark:嵌入式人工智能工具的自动化与基准测试系统——论文阅读
|
人工智能 缓存 自然语言处理
别再手搓测试数据了!AE测试数据智造系统揭秘
本文介绍如何通过构建基于大语言模型的测试数据智造Agent,解决AliExpress跨境电商测试中数据构造复杂、低效的问题,推动测试效率提升与智能化转型。
别再手搓测试数据了!AE测试数据智造系统揭秘
|
9月前
|
存储 测试技术 API
数据驱动开发软件测试脚本
今天刚提交了我的新作《带着ChatGPT玩转软件开发》给出版社,在写作期间跟着ChatGPT学到许多新知识。下面分享数据驱动开发软件测试脚本。
383 0
|
jenkins 测试技术 Shell
利用Apipost轻松实现用户充值系统的API自动化测试
API在现代软件开发中扮演着连接不同系统与模块的关键角色,其测试的重要性日益凸显。传统API测试面临效率低、覆盖率不足及难以融入自动化工作流等问题。Apipost提供了一站式API自动化测试解决方案,支持零代码拖拽编排、全场景覆盖,并可无缝集成CI/CD流程。通过可视化界面,研发与测试人员可基于同一数据源协作,大幅提升效率。同时,Apipost支持动态数据提取、性能压测等功能,满足复杂测试需求。文档还以用户充值系统为例,详细介绍了从创建测试用例到生成报告的全流程,帮助用户快速上手并提升测试质量。
1328 18
|
数据可视化 前端开发 测试技术
接口测试新选择:Postman替代方案全解析
在软件开发中,接口测试工具至关重要。Postman长期占据主导地位,但随着国产工具的崛起,越来越多开发者转向更适合中国市场的替代方案——Apifox。它不仅支持中英文切换、完全免费不限人数,还具备强大的可视化操作、自动生成文档和API调试功能,极大简化了开发流程。
|
Java 测试技术 容器
Jmeter工具使用:HTTP接口性能测试实战
希望这篇文章能够帮助你初步理解如何使用JMeter进行HTTP接口性能测试,有兴趣的话,你可以研究更多关于JMeter的内容。记住,只有理解并掌握了这些工具,你才能充分利用它们发挥其应有的价值。+
1612 23
|
SQL 安全 测试技术
2025接口测试全攻略:高并发、安全防护与六大工具实战指南
本文探讨高并发稳定性验证、安全防护实战及六大工具(Postman、RunnerGo、Apipost、JMeter、SoapUI、Fiddler)选型指南,助力构建未来接口测试体系。接口测试旨在验证数据传输、参数合法性、错误处理能力及性能安全性,其重要性体现在早期发现问题、保障系统稳定和支撑持续集成。常用方法包括功能、性能、安全性及兼容性测试,典型场景涵盖前后端分离开发、第三方服务集成与数据一致性检查。选择合适的工具需综合考虑需求与团队协作等因素。
2141 24
|
JSON 前端开发 测试技术
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡
1232 10
大前端之前端开发接口测试工具postman的使用方法-简单get接口请求测试的使用方法-简单教学一看就会-以实际例子来说明-优雅草卓伊凡