``` FOR 循环 "batchSize": 1000 2025-07-29 14:50:35 [XNIO-1 task-2] INFO c.c.p.g.s.GwForwardRecordService:364 - 测试数据生成完成,总计: 100 条 2025-07-29 14:50:35 [XNIO-1 task-2] INFO c.c.p.c.w.i.PlusWebInvokeTimeInterceptor:81 - [PLUS]结束请求 => URL[POST /gateway/record/generate-test-data],耗时:[12,736]毫秒 2025-07-29 14:53:15 [XNIO-1 task-2] INFO c.c.p.g.s.GwForwardRecordService:364 - 测试数据生成完成,总计: 1000 条 2025-07-29 14:53:15 [XNIO-1 task-2] INFO c.c.p.c.w.i.PlusWebInvokeTimeInterceptor:81 - [PLUS]结束请求 => URL[POST /gateway/record/generate-test-data],耗时:[65,119]毫秒 2025-07-29 15:05:18 [XNIO-1 task-2] INFO c.c.p.g.s.GwForwardRecordService:364 - 测试数据生成完成,总计: 2000 条 2025-07-29 15:05:18 [XNIO-1 task-2] INFO c.c.p.c.w.i.PlusWebInvokeTimeInterceptor:81 - [PLUS]结束请求 => URL[POST /gateway/record/generate-test-data],耗时:[131919]毫秒 批量插入 "batchSize": 1000 2025-07-29 15:13:02 [XNIO-1 task-2] INFO c.c.p.g.s.GwForwardRecordService:357 - 测试数据生成完成,总计: 1000 条 2025-07-29 15:13:02 [XNIO-1 task-2] INFO c.c.p.c.w.i.PlusWebInvokeTimeInterceptor:81 - [PLUS]结束请求 => URL[POST /gateway/record/generate-test-data],耗时:[1153]毫秒 2025-07-29 15:13:40 [XNIO-1 task-2] INFO c.c.p.g.s.GwForwardRecordService:357 - 测试数据生成完成,总计: 10000 条 2025-07-29 15:13:40 [XNIO-1 task-2] INFO c.c.p.c.w.i.PlusWebInvokeTimeInterceptor:81 - [PLUS]结束请求 => URL[POST /gateway/record/generate-test-data],耗时:[6060]毫秒 "batchSize": 2000 2025-07-29 15:14:32 [XNIO-1 task-2] INFO c.c.p.g.s.GwForwardRecordService:357 - 测试数据生成完成,总计: 10000 条 2025-07-29 15:14:32 [XNIO-1 task-2] INFO c.c.p.c.w.i.PlusWebInvokeTimeInterceptor:81 - [PLUS]结束请求 => URL[POST /gateway/record/generate-test-data],耗时:[8088]毫秒 "batchSize": 3000 2025-07-29 15:15:02 [XNIO-1 task-2] INFO c.c.p.g.s.GwForwardRecordService:357 - 测试数据生成完成,总计: 10000 条 2025-07-29 15:15:02 [XNIO-1 task-2] INFO c.c.p.c.w.i.PlusWebInvokeTimeInterceptor:81 - [PLUS]结束请求 => URL[POST /gateway/record/generate-test-data],耗时:[9107]毫秒 "batchSize": 1000 2025-07-29 15:16:40 [XNIO-1 task-2] INFO c.c.p.g.s.GwForwardRecordService:357 - 测试数据生成完成,总计: 50000 条 2025-07-29 15:16:40 [XNIO-1 task-2] INFO c.c.p.c.w.i.PlusWebInvokeTimeInterceptor:81 - [PLUS]结束请求 => URL[POST /gateway/record/generate-test-data],耗时:[39666]毫秒【数据犯了5倍,但时间6倍】 "batchSize": 5000 2025-07-29 15:18:37 [XNIO-1 task-2] INFO c.c.p.g.s.GwForwardRecordService:357 - 测试数据生成完成,总计: 50000 条 2025-07-29 15:18:37 [XNIO-1 task-2] INFO c.c.p.c.w.i.PlusWebInvokeTimeInterceptor:81 - [PLUS]结束请求 => URL[POST /gateway/record/generate-test-data],耗时:[45076]毫秒【多了十五秒】 ``` ### 最左前缀原则 ``` /** * 生成测试数据 */ @PostMapping("/generate-test-data") public R generateTestData(@Valid @RequestBody GwForwardRecordTestDataReq request) { long startTime = System.currentTimeMillis(); gwForwardRecordService.generateTestData(request); long endTime = System.currentTimeMillis(); String message = String.format("成功生成 %d 条测试数据,耗时 %d 毫秒", request.getCount(), endTime - startTime); return R.ok(message); } /** * 生成测试数据 */ public void generateTestData(GwForwardRecordTestDataReq request) { log.info("开始生成测试数据,数量: {}", request.getCount()); // 设置默认时间范围 LocalDateTime endTime = request.getEndTime() != null ? request.getEndTime() : LocalDateTime.now(); LocalDateTime startTime = request.getStartTime() != null ? request.getStartTime() : endTime.minusDays(7); // 获取路由配置 Map routeNameToIdMap = gwRouteConfigService.selectRouteNameToIdMap(); if (routeNameToIdMap.isEmpty()) { throw new RuntimeException("没有找到路由配置,请先配置路由"); } List routeNames = new ArrayList<>(routeNameToIdMap.keySet()); int batchSize = request.getBatchSize(); int totalCount = request.getCount(); int processedCount = 0; try { while (processedCount < totalCount) { int currentBatchSize = Math.min(batchSize, totalCount - processedCount); List records = generateBatchTestData(currentBatchSize, startTime, endTime, routeNames, routeNameToIdMap); // 批量插入主表数据 recordMapper.insertBatch(records, currentBatchSize); processedCount += currentBatchSize; if (processedCount % (batchSize * 10) == 0) { log.info("已生成测试数据: {}/{}", processedCount, totalCount); } } log.info("测试数据生成完成,总计: {} 条", totalCount); } catch (Exception e) { log.error("生成测试数据失败", e); throw new RuntimeException("生成测试数据失败: " + e.getMessage()); } } /** * 生成批量测试数据 */ private List generateBatchTestData(int count, LocalDateTime startTime, LocalDateTime endTime, List routeNames, Map routeNameToIdMap) { List records = new ArrayList<>(count); ThreadLocalRandom random = ThreadLocalRandom.current(); // 预定义的API路径模板 String[] apiPaths = { "/api/v1/user/login", "/api/v1/user/logout", "/api/v1/user/profile", "/api/v2/sync/BBOSS/PreCheckServ", "/api/v2/sync/BBOSS/QueryServ", "/api/v2/sync/BBOSS/UpdateServ", "/api/v1/order/create", "/api/v1/order/query", "/api/v1/order/update", "/api/v1/order/cancel", "/api/v1/payment/create", "/api/v1/payment/query", "/api/v1/payment/callback", "/api/v1/product/list", "/api/v1/product/detail", "/api/v1/product/search", "/api/v1/system/health", "/api/v1/system/config", "/api/v1/system/monitor" }; // HTTP方法 String[] methods = {"GET", "POST", "PUT", "DELETE"}; // 目标服务地址 String[] targetEndpoints = { "127.0.0.1:8080", "127.0.0.1:8081", "127.0.0.1:8082", "192.168.1.100:8080", "192.168.1.101:8080", "192.168.1.102:8080" }; // 网关地址 String[] gatewayEndpoints = { "192.168.208.16:8087", "192.168.208.17:8087", "192.168.208.18:8087" }; // HTTP状态码权重分布(模拟真实场景) int[] httpCodes = {200, 200, 200, 200, 200, 200, 200, 200, 200, 201, 400, 401, 403, 404, 500, 502, 503}; long startTimestamp = startTime.atZone(java.time.ZoneId.systemDefault()).toInstant().toEpochMilli(); long endTimestamp = endTime.atZone(java.time.ZoneId.systemDefault()).toInstant().toEpochMilli(); for (int i = 0; i < count; i++) { // 随机生成时间 long randomTimestamp = random.nextLong(startTimestamp, endTimestamp); LocalDateTime requestTime = LocalDateTime.ofInstant( java.time.Instant.ofEpochMilli(randomTimestamp), java.time.ZoneId.systemDefault()); // 随机选择路由 String routeName = routeNames.get(random.nextInt(routeNames.size())); // 生成UUID和TraceId String uuid = java.util.UUID.randomUUID().toString(); String traceId = uuid.replace("-", "").substring(0, 16); // 随机选择API路径 String requestUrl = apiPaths[random.nextInt(apiPaths.length)]; // 随机选择HTTP方法 String method = methods[random.nextInt(methods.length)]; // 随机选择目标地址 String targetEndpoint = targetEndpoints[random.nextInt(targetEndpoints.length)]; // 随机选择网关地址 String gatewayEndpoint = gatewayEndpoints[random.nextInt(gatewayEndpoints.length)]; // 随机选择HTTP状态码 Integer httpCode = httpCodes[random.nextInt(httpCodes.length)]; // 生成响应时间(模拟真实分布) Integer costTime = generateRealisticCostTime(random, httpCode); GwForwardRecord record = GwForwardRecord.builder() .uuid(uuid) .requestTime(requestTime) .requestUrl(requestUrl) .method(method) .targetEndpoint(targetEndpoint) .httpCode(httpCode) .traceId(traceId) .gatewayEndpoint(gatewayEndpoint) .routeId(routeNameToIdMap.get(routeName)) .costTime(costTime) .build(); records.add(record); } return records; } /** * 生成真实的响应时间分布 */ private Integer generateRealisticCostTime(ThreadLocalRandom random, Integer httpCode) { // 根据HTTP状态码生成不同的响应时间分布 if (httpCode >= 200 && httpCode < 300) { // 成功请求:大部分在100-2000ms之间,少数较慢 if (random.nextDouble() < 0.8) { return random.nextInt(100, 2000); // 80%的请求在100-2000ms } else if (random.nextDouble() < 0.95) { return random.nextInt(2000, 5000); // 15%的请求在2-5秒 } else { return random.nextInt(5000, 15000); // 5%的请求在5-15秒 } } else if (httpCode >= 400 && httpCode < 500) { // 客户端错误:通常较快 return random.nextInt(50, 1000); } else if (httpCode >= 500) { // 服务器错误:可能很慢或超时 if (random.nextDouble() < 0.7) { return random.nextInt(1000, 10000); // 70%在1-10秒 } else { return random.nextInt(10000, 30000); // 30%在10-30秒 } } else { // 其他状态码 return random.nextInt(100, 3000); } } ```