Files
notes/work/移动杭研/开发记录/7.12.0/测试数据.md
T
2026-03-01 01:43:46 +08:00

10 KiB

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<String> 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<String, Long> routeNameToIdMap = gwRouteConfigService.selectRouteNameToIdMap();  
    if (routeNameToIdMap.isEmpty()) {  
        throw new RuntimeException("没有找到路由配置,请先配置路由");  
    }  
  
    List<String> 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<GwForwardRecord> 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<GwForwardRecord> generateBatchTestData(int count, LocalDateTime startTime, LocalDateTime endTime,  
                                                   List<String> routeNames, Map<String, Long> routeNameToIdMap) {  
    List<GwForwardRecord> 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);  
    }  
}