Gatling负载测试中重复对象生成问题排查求助
Gatling结合DataFaker负载测试重复生成对象问题的原因与解决
问题描述
使用Gatling搭配DataFaker开展大规模负载测试时,发现测试代码重复生成相同对象,通过API执行日志确认了该问题,严重影响测试结果准确性。
初始代码(存在问题)
public class ApiSimulation extends Simulation { private final Faker faker = new Faker(Locale.forLanguageTag("pt_BR")); /** * 创建HTTP协议 */ private final HttpProtocolBuilder httpProtocolBuilder = http .baseUrl("http://localhost:8081") .userAgentHeader("Mozilla/5.0"); /** * 创建数据插入场景 */ private final ScenarioBuilder insertAlunosScenario = scenario("批量数据插入") .feed(listFeeder(List.of( Map.of("id", UUID.randomUUID(), "nome", faker.name().fullName(), "idade", faker.number().numberBetween(3, 17), "email", faker.internet().emailAddress(), "sexo", faker.gender().shortBinaryTypes().toUpperCase(), "dataInsercao", LocalDateTime.now(), "dataAlteracao", LocalDateTime.now()))) .random()) .exec(http("创建学生") .post("/alunos") .header("Content-Type", "application/json") .body(ElFileBody("alunoTemplate.json")) .asJson() .check(status().in(201, 400, 422, 500))); { setUp(insertAlunosScenario.injectOpen( constantUsersPerSec(10_000).during(of(10, SECONDS)))) .protocols(httpProtocolBuilder); } }
修改后的代码(解决问题)
public class ApiSimulation extends Simulation { private final Faker faker = new Faker(Locale.forLanguageTag("pt_BR")); private final Iterator<Map<String, Object>> feeder = Stream.generate(() -> { Map<String, Object> map = new HashMap<>(); map.put("id", UUID.randomUUID()); map.put("nome", faker.name().fullName()); map.put("idade", faker.number().numberBetween(3, 17)); map.put("email", faker.internet().emailAddress()); map.put("sexo", faker.gender().shortBinaryTypes().toUpperCase()); map.put("dataInsercao", LocalDateTime.now()); map.put("dataAlteracao", LocalDateTime.now()); return map; }).iterator(); /** * 创建HTTP协议 */ private final HttpProtocolBuilder httpProtocolBuilder = http .baseUrl("http://localhost:8081") .userAgentHeader("Mozilla/5.0"); /** * 创建数据插入场景 */ private final ScenarioBuilder insertAlunosScenario = scenario("批量数据插入") .feed(feeder) .exec(http("创建学生") .post("/alunos") .header("Content-Type", "application/json") .body(StringBody( """\n {\n "id": "#{id}",\n "nome": "#{nome}",\n "idade": "#{idade}",\n "email": "#{email}",\n "sexo": "#{sexo}",\n "dataInsercao": "#{dataInsercao}",\n "dataAlteracao": "#{dataAlteracao}"\n }\n """ )) .asJson() .check(status().in(201, 400, 422, 500))); { setUp(insertAlunosScenario.injectOpen( constantUsersPerSec(10).during(of(10, SECONDS)))) .protocols(httpProtocolBuilder); } }
原因分析
初始代码的问题核心在于数据生成时机错误:
- 使用
List.of()创建了仅包含一个元素的列表,所有随机数据(UUID、Faker生成的姓名/邮箱等)都是在Simulation类初始化阶段一次性生成的,而非每次请求时动态生成。 - 后续调用
listFeeder(...).random()时,只是在这个唯一的元素里循环取用,导致所有请求都复用同一组数据,自然出现重复对象。
解决方案说明
修改后的代码通过以下方式解决了重复问题:
- 使用
Stream.generate(() -> {...})创建一个无限流,每次调用流的生成器都会执行lambda表达式,动态生成新的随机数据Map,确保每个请求都能获取到全新的对象。 - 转换为Iterator后作为Feeder传入,Gatling每次执行
feed(feeder)时都会从Iterator中取出下一个新生成的Map,彻底避免了数据复用。
额外注意事项:
- DataFaker的
Faker实例是线程安全的,多个线程并发调用其方法不会导致数据冲突或重复,因此无需为每个线程单独创建Faker实例。 - 如果需要更复杂的动态数据生成逻辑,可以在lambda表达式中进一步扩展,比如添加更多业务规则或随机逻辑。
内容的提问来源于stack exchange,提问作者Diego Macario
相关产品推荐
相关产品推荐

