Initial commit
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
# 网关转发记录曲线图接口说明
|
||||
|
||||
## 接口概述
|
||||
|
||||
新增了一个高效的曲线图数据查询接口,用于展示网关转发记录的统计数据。该接口支持多种时间粒度的聚合查询,并提供丰富的过滤条件。
|
||||
|
||||
## 接口信息
|
||||
|
||||
- **接口路径**: `POST /gateway/record/chart`
|
||||
- **请求方式**: POST
|
||||
- **Content-Type**: application/json
|
||||
|
||||
## 请求参数
|
||||
|
||||
### 必填参数
|
||||
|
||||
| 参数名 | 类型 | 说明 | 示例 |
|
||||
|--------|------|------|------|
|
||||
| startTime | LocalDateTime | 查询开始时间 | "2024-01-01 00:00:00" |
|
||||
| endTime | LocalDateTime | 查询结束时间 | "2024-01-01 23:59:59" |
|
||||
| timeGranularity | String | 时间粒度 | "5MIN" |
|
||||
|
||||
### 时间粒度选项
|
||||
|
||||
| 值 | 说明 | 聚合方式 |
|
||||
|----|------|----------|
|
||||
| 5MIN | 5分钟 | 按5分钟间隔聚合(00:00-00:04, 00:05-00:09…) |
|
||||
| 1HOUR | 1小时 | 按小时聚合 |
|
||||
| 1DAY | 1天 | 按天聚合 |
|
||||
| 1WEEK | 1周 | 按周聚合(周一为起始) |
|
||||
| 1MONTH | 1月 | 按月聚合 |
|
||||
|
||||
### 可选过滤参数
|
||||
|
||||
| 参数名 | 类型 | 说明 | 是否支持模糊查询 |
|
||||
|--------|------|------|------------------|
|
||||
| requestUrl | String | 接口路径 | ✅ |
|
||||
| method | String | 请求方法 | ❌ |
|
||||
| targetEndpoint | String | 目的地址 | ✅ |
|
||||
| httpCode | Integer | HTTP状态码 | ❌ |
|
||||
| gatewayEndpoint | String | 网关地址 | ✅ |
|
||||
| minCostTime | Integer | 最小耗时(ms) | ❌ |
|
||||
| maxCostTime | Integer | 最大耗时(ms) | ❌ |
|
||||
| routeId | Long | 路由ID | ❌ |
|
||||
| routeName | String | 路由名称 | ✅ |
|
||||
|
||||
## 请求示例
|
||||
|
||||
```json
|
||||
{
|
||||
"startTime": "2024-01-01 00:00:00", "endTime": "2024-01-01 23:59:59", "timeGranularity": "1HOUR", "requestUrl": "/api/user", "method": "GET", "minCostTime": 100, "maxCostTime": 5000}
|
||||
```
|
||||
|
||||
## 响应数据结构
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200, "msg": "操作成功",
|
||||
"data": { "dataPoints": [ { "timePoint": "2024-01-01 00:00:00", "count2xx": 150, "count4xx": 10, "count5xx": 2, "countOther": 1, "avgCostTime": 245.67 }, { "timePoint": "2024-01-01 01:00:00", "count2xx": 200, "count4xx": 15, "count5xx": 3, "countOther": 0, "avgCostTime": 198.34 } ] }}
|
||||
```
|
||||
|
||||
## 响应字段说明
|
||||
|
||||
### dataPoints 数组中每个元素的字段
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|--------|------|------|
|
||||
| timePoint | LocalDateTime | 时间点(X轴) |
|
||||
| count2xx | Long | 2xx状态码请求次数(左Y轴) |
|
||||
| count4xx | Long | 4xx状态码请求次数(左Y轴) |
|
||||
| count5xx | Long | 5xx状态码请求次数(左Y轴) |
|
||||
| countOther | Long | 其他状态码请求次数(左Y轴) |
|
||||
| avgCostTime | BigDecimal | 平均耗时ms,保留2位小数(右Y轴) |
|
||||
|
||||
## 性能优化说明
|
||||
|
||||
1. **索引优化**: 建议在 `request_time` 字段上创建索引以提高查询效率
|
||||
2. **模糊查询**: 仅在 `requestUrl`、`targetEndpoint`、`gatewayEndpoint`、`routeName` 字段支持模糊查询
|
||||
3. **时间范围**: 建议查询时间范围不要过大,以保证响应速度
|
||||
4. **聚合查询**: 使用数据库层面的聚合查询,减少内存占用
|
||||
|
||||
## 前端图表建议
|
||||
|
||||
- **左Y轴**: 显示请求次数(count2xx, count4xx, count5xx, countOther)
|
||||
- **右Y轴**: 显示平均耗时(avgCostTime)
|
||||
- **X轴**: 显示时间(timePoint)
|
||||
- **图表类型**: 建议使用折线图或柱状图
|
||||
- **颜色建议**:
|
||||
- 2xx: 绿色(成功)
|
||||
- 4xx: 橙色(客户端错误)
|
||||
- 5xx: 红色(服务器错误)
|
||||
- 其他: 灰色
|
||||
- 平均耗时: 蓝色
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 时间粒度为左闭右开区间
|
||||
2. 大数据量查询时建议适当限制时间范围
|
||||
3. 模糊查询会影响性能,请谨慎使用
|
||||
4. 平均耗时为0表示该时间段内没有有效的耗时数据
|
||||
@@ -0,0 +1,96 @@
|
||||
这是我的请求记录表:
|
||||
|
||||
对应的 mapper 等文件在:
|
||||
|
||||
`D:\MyCode\Work\yd-hy\ibs-plus\plus-service\src\main\java\com\cmcc\plus\gateway`
|
||||
|
||||
`D:\MyCode\Work\yd-hy\ibs-plus\plus-service\src\main\resources\mapper\gateway`
|
||||
|
||||
表结构:
|
||||
|
||||
```java
|
||||
@TableName(value = "gw_forward_record")
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class GwForwardRecord implements Serializable {
|
||||
/**
|
||||
* 记录ID
|
||||
*/
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long recordId;
|
||||
|
||||
/**
|
||||
* 请求UUID
|
||||
*/
|
||||
private String uuid;
|
||||
|
||||
/**
|
||||
* 请求时间
|
||||
*/
|
||||
private LocalDateTime requestTime;
|
||||
|
||||
/**
|
||||
* 接口路径
|
||||
*/
|
||||
private String requestUrl;
|
||||
|
||||
/**
|
||||
* 请求方法
|
||||
*/
|
||||
private String method;
|
||||
|
||||
/**
|
||||
* 目的地址
|
||||
*/
|
||||
private String targetEndpoint;
|
||||
|
||||
/**
|
||||
* 请求响应码
|
||||
*/
|
||||
private Integer httpCode;
|
||||
|
||||
/**
|
||||
* 链路追踪ID
|
||||
*/
|
||||
private String traceId;
|
||||
|
||||
/**
|
||||
* 网关地址
|
||||
*/
|
||||
private String gatewayEndpoint;
|
||||
|
||||
/**
|
||||
* 请求匹配的路由ID
|
||||
*/
|
||||
private Long routeId;
|
||||
|
||||
/**
|
||||
* 请求耗时(ms)
|
||||
*/
|
||||
private Integer costTime;
|
||||
|
||||
@Serial
|
||||
@TableField(exist = false)
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
```
|
||||
|
||||
我现在有一个需求,需要给前端提供一个曲线图数据查询接口:
|
||||
|
||||
接口创建在 com.cmcc.plus.web.controller.gateway.GwForwardRecordController 下。
|
||||
|
||||
注意一定要保证代码执行效率。因为这是网关请求记录表,是一个量级非常大的表。
|
||||
|
||||
图中包含 5 条线:2xx、4xx、5xx、其他状态码(请求次数,对应表httpCode字段)、平均耗时(ms,对应表 costTime 字段)
|
||||
|
||||
我的图标左侧 Y 轴为 请求次数,右侧 Y 轴 平均耗时。下方 X 轴为时间坐标轴。
|
||||
|
||||
我想给我前端一个通用方法,查询某个时间段的这五个指标(也就是针对 requestTime 的过滤)。costTime(比如前端传 200ms-300ms 的查询)同时支持通过 requestUrl、method、targetEndpoint、httpCode、gatewayEndpoint 的过滤。
|
||||
|
||||
请仔细设计返回前端的结构体,做到最标准和效率。
|
||||
|
||||
仔细设计 requestUrl、targetEndpoint、gatewayEndpoint 是否可以使用模糊查询,前提是保证效率,因为这个表是一个非常大的表。
|
||||
|
||||
针对时间粒度。帮我提供时间区间内 5 分钟(例如 00:00:00 的数据就是 00:00:00-00:04:59),1小时,1天,一周,一月。时间粒度均为左闭右开。这个粒度根据前端选择进行聚合。不用一次全聚合出来。
|
||||
@@ -0,0 +1,81 @@
|
||||
# 客户运营数据统计-新增累计商用客户数试用客户数等6项统计及页面展示
|
||||
|
||||
NRWLXT-29935
|
||||
|
||||
## 需求评审
|
||||
|
||||
## 需求备注
|
||||
|
||||
## 需求开发
|
||||
|
||||
# 集客大厅前置校验新增信安校验多sheet提示
|
||||
|
||||
NRWLXT-29939
|
||||
|
||||
## 需求评审
|
||||
|
||||
## 需求备注
|
||||
|
||||
## 需求开发
|
||||
|
||||
# 用例评审
|
||||
|
||||
# 冒烟自测
|
||||
|
||||
## 订购迁移工单
|
||||
|
||||
1、IBS测试环境:https://test.p.cdn.10086.cn
|
||||
|
||||
2、IBS存在esop企业A、已业务开通:网页加速的订购ID:20230000810、企业CP_ID:83000001
|
||||
|
||||
esop企业B、已业务开通超低时延直播加速订购ID:20240000001,订购下域名test1.com、test2.com、test3.com,域名状态:已生效、企业CP_ID:83000002
|
||||
|
||||
---
|
||||
|
||||
网页加速
|
||||
|
||||
ECName1753237067、ECID1753237067、DevReq1753237067A.komect.com、PRODUCTID1753237241、83569731
|
||||
|
||||
超低时延直播
|
||||
|
||||
ECName1753237499、ECID1753237499、DevReq1753237499A.komect.com、PRODUCTID1753237683、83559505
|
||||
|
||||
## 订购迁移工单下发BPM同步平面信息
|
||||
|
||||
1、IBS测试环境:https://test.p.cdn.10086.cn
|
||||
|
||||
2、IBS存在esop企业A、已业务开通:网页加速的订购ID:20230000810、业务开通的产品类型-移动网内CDN 分发平面:华为平面
|
||||
|
||||
esop企业B、已业务开通超低时延直播加速订购ID:20240000001,订购下域名test1.com、test2.com、test3.com,域名状态:已生效、业务开通的产品类型-三网CDN
|
||||
|
||||
---
|
||||
|
||||
ECName1753239995
|
||||
|
||||
页面
|
||||
|
||||
PRODUCTID1753240145
|
||||
|
||||
域名状态已生效
|
||||
|
||||
---
|
||||
|
||||
1、IBS测试环境:https://test.p.cdn.10086.cn
|
||||
|
||||
2、IBS存在esop企业A、已业务开通:网页加速的订购ID:20230000810、业务开通的产品类型-移动网内CDN 分发平面:华为平面
|
||||
|
||||
esop企业B、已业务开通超低时延直播加速订购ID:20240000001,订购下域名test1.com、test2.com、test3.com,域名状态:已生效、业务开通的产品类型-三网CDN
|
||||
|
||||
## 企业客户域名列表展示
|
||||
|
||||
1、IBS测试环境:https://test.p.cdn.10086.cn
|
||||
|
||||
2、IBS已存在esop企业Test、企业下域名www.test.com
|
||||
|
||||
3、esop企业A账号下已新增冲突域名:www.test.com.01.cdnhwcqir15.com,产品类型:网页加速
|
||||
|
||||
## 通用客户域名列表查询接口-域名列表查询
|
||||
|
||||
1、IBS已存在归属A企业下域名testa.com,状态为已生效
|
||||
|
||||
2、IBS已存在归属B企业下真实域名:testa.com,虚拟域名:testa.com.01.cdnhwcqir15.com,下发平面为华为平面,状态为已生效
|
||||
@@ -0,0 +1,224 @@
|
||||
```
|
||||
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);
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user