JMeter压力测试的数据准备和清理自动化是重点,不是简单写个脚本造数或删数,而是用可控的生命周期、唯一批次标识和跨线程组传递机制,保证每轮压测数据可追溯、可隔离、可回收。JMeter原生的setUp Thread Group 和 tearDown Thread Group是最自然的自动化骨架:前者在所有主线程组之前执行数据准备,后者在所有主线程组结束后执行清理,不需要额外调度,也不容易被并发配置干扰。
整体上建议分三层设计。第一层是生命周期骨架,用setUp做Pre、tearDown做Post。第二层是技术手段选型:关系型数据库的批量增删优先用 JDBC Request;复杂数据生成、规则检查、跨数据源编排用 JSR223 + Groovy;系统命令、Python/Shell造数脚本用 OS Process Sampler 外包出去,JMeter只做调度。第三层是隔离和追溯原则:清理不能一锅端,必须只删除本轮测试创建的数据,因此准备阶段要为每条数据打唯一批次标识,比如时间戳、UUID或业务前缀,清理阶段以该标识为条件删除。
数据准备方面,常见有三种做法。第一种是在 setUp Thread Group 中用 JDBC Connection Configuration 加 JDBC Request,Query Type 选 Prepared Update Statement,配合循环控制器和计数器批量插入。插入时把生成的用户名、订单号或批次字段一并写入,并通过 props.put() 把批次标识暴露给全局。第二种是用 JSR223 + Groovy 创建数据工厂,把用户—订单—优惠券等关联数据、身份证/银行卡检查规则、唯一性检查封装成 Groovy 方法或脚本文件,在 setUp中集中调用。Groovy可以直接引入第三方JAR,也能调用JDBC驱动检查唯一性,性能明显优于BeanShell。第三种是混合编排:如果造数思路很重,不必全塞进JMeter,在 setUp 中放一个 OS Process Sampler 调用外部Python/Shell脚本,JMeter只等待退出码并接收输出参数,保持脚本轻量。
数据清理的原则是根据本轮标识准确删除。准备阶段生成一个全局批次属性,如 props.put("batchId", System.currentTimeMillis().toString()),每条测试数据落库时把 batchId 写入某个来源批次字段。tearDown 中执行 DELETE FROM xxx WHERE source_batch = '${__P(batchId)}',或者调用对应删除接口。这样即使测试异常中断、部分数据已经产生,下一轮 setUp 也能用相同前缀做残留清扫,形成自愈能力。
清理手段可以选 JDBC 直接删除、调用删除API,或分层清理。直接删库适合数据表结构简单、无业务状态机的场景;如果删除涉及取消、审批、权限检查,应在 tearDown 中用 HTTP Request 调用系统删除接口,参数取自准备阶段存入的变量。对于压测中产生的大量临时数据,不必全部留到最后,可以在主线程组迭代内部用 JSR223 PostProcessor 做即时轻量清理,只把需要跨迭代复用的重要数据留给 tearDown,降低一次性大批量删除的超时风险。
跨线程组传递变量是自动化:JMeter变量是线程局部的,setUp 生成的数据标识必须通过 props 全局属性传给主线程组和 tearDown;复杂结构可以序列化后存入props或用文件做中介。脚本语言优先Groovy,避免BeanShell,因为高并发下 BeanShell 的性能短板和内存泄漏风险会被放大。失败途径也要设计清理:tearDown默认仍会执行,建议加先查后删的容错思路,某些ID已不存在时不要让整个tearDown失败,可用 Ignore Status或Groovy异常捕获处理。准备和清理的对称性比聪明更重要:setUp 做了什么,tearDown就精确回滚什么;中间压测思路尽量不直接操作持久化数据,所有落库或落盘动作都带批次标识,这样测试计划迭代后数据卫生仍然可控。