chore: initial import
This commit is contained in:
34
test/perf/PERF_ENV.md
Normal file
34
test/perf/PERF_ENV.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# AI-Ops 性能压测环境规格
|
||||
|
||||
## 压测目标
|
||||
|
||||
| 场景 | 并发用户 | 目标 P95 | 目标 P99 | 失败率门槛 |
|
||||
|------|----------|----------|----------|------------|
|
||||
| 首页加载 | 50 | < 2s | < 3s | < 1% |
|
||||
| 指标下钻 | 20 | < 3s | < 5s | < 1% |
|
||||
| 告警触发到通知 | - | < 30s | < 60s | < 0.1% |
|
||||
|
||||
## 环境规格
|
||||
|
||||
| 组件 | 规格 | 说明 |
|
||||
|------|------|------|
|
||||
| AI-Ops API Server | 2 vCPU / 4GB 内存 | 与生产目标一致 |
|
||||
| PostgreSQL | 2 vCPU / 4GB 内存 / SSD | 含 10 万条审计日志基准数据 |
|
||||
| Redis | 1 vCPU / 2GB 内存 | 用于告警抑制缓存 |
|
||||
| Prometheus | 独立实例 | 采集 10 个指标、15s 间隔 |
|
||||
|
||||
## 压测方法
|
||||
|
||||
1. **首页加载**:`k6 run test/perf/dashboard_k6.js`
|
||||
2. **下钻查询**:`k6 run test/perf/drilldown_k6.js`
|
||||
3. **告警延迟**:通过 Go 单测 `alert_latency_test.go` 测量触发到通知的延迟
|
||||
|
||||
## P99 计算方法
|
||||
|
||||
使用 k6 默认统计方法:在压测期间(10s 滑动窗口)内的所有请求响应时间排序后取 99% 分位数。
|
||||
|
||||
## 通过标准
|
||||
|
||||
- P95 达标且失败率 < 1% → 通过
|
||||
- P95 超标但 P99 达标 → CONDITIONAL_APPROVED(需性能优化)
|
||||
- P99 超标 → 阻止进入下一阶段
|
||||
29
test/perf/alert_latency_test.go
Normal file
29
test/perf/alert_latency_test.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package perf
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// TestAlertLatency 测量告警触发到通知的延迟
|
||||
// 目标:< 30s (P95)
|
||||
func TestAlertLatency(t *testing.T) {
|
||||
// 模拟规则触发
|
||||
triggeredAt := time.Now()
|
||||
|
||||
// TODO: 替换为实际的告警服务调用
|
||||
// alert, err := alertService.Evaluate(ctx, ruleID)
|
||||
// require.NoError(t, err)
|
||||
|
||||
// 模拟通知发送
|
||||
// err = notifyService.Send(ctx, alert)
|
||||
// require.NoError(t, err)
|
||||
|
||||
// 计算延迟
|
||||
latency := time.Since(triggeredAt)
|
||||
|
||||
t.Logf("Alert latency: %v", latency)
|
||||
assert.Less(t, latency, 30*time.Second, "alert latency should be < 30s")
|
||||
}
|
||||
32
test/perf/dashboard_k6.js
Normal file
32
test/perf/dashboard_k6.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import http from 'k6/http';
|
||||
import { check, sleep } from 'k6';
|
||||
|
||||
// AI-Ops 看板首页性能压测脚本
|
||||
// 目标:验证首页加载 < 2s,并发 50 用户
|
||||
|
||||
export const options = {
|
||||
stages: [
|
||||
{ duration: '1m', target: 50 }, // 逐步加载到 50 并发
|
||||
{ duration: '3m', target: 50 }, // 稳定压测 3 分钟
|
||||
{ duration: '1m', target: 0 }, // 逐步卸载
|
||||
],
|
||||
thresholds: {
|
||||
http_req_duration: ['p(95)<2000'], // P95 < 2s
|
||||
http_req_duration: ['p(99)<3000'], // P99 < 3s
|
||||
http_req_failed: ['rate<0.01'], // 失败率 < 1%
|
||||
},
|
||||
};
|
||||
|
||||
export default function () {
|
||||
const url = 'http://localhost:8080/api/v1/ai-ops/dashboard';
|
||||
const res = http.get(url, {
|
||||
headers: { 'Authorization': 'Bearer ${__ENV.AI_OPS_TOKEN}' },
|
||||
});
|
||||
|
||||
check(res, {
|
||||
'status is 200': (r) => r.status === 200,
|
||||
'response time < 2s': (r) => r.timings.duration < 2000,
|
||||
});
|
||||
|
||||
sleep(1);
|
||||
}
|
||||
32
test/perf/drilldown_k6.js
Normal file
32
test/perf/drilldown_k6.js
Normal file
@@ -0,0 +1,32 @@
|
||||
import http from 'k6/http';
|
||||
import { check, sleep } from 'k6';
|
||||
|
||||
// AI-Ops 下钻性能压测脚本
|
||||
// 目标:验证下钻加载 < 3s,并发 20 用户
|
||||
|
||||
export const options = {
|
||||
stages: [
|
||||
{ duration: '30s', target: 20 },
|
||||
{ duration: '2m', target: 20 },
|
||||
{ duration: '30s', target: 0 },
|
||||
],
|
||||
thresholds: {
|
||||
http_req_duration: ['p(95)<3000'], // P95 < 3s
|
||||
http_req_failed: ['rate<0.01'], // 失败率 < 1%
|
||||
},
|
||||
};
|
||||
|
||||
export default function () {
|
||||
const service = `service_${Math.floor(Math.random() * 10)}`;
|
||||
const url = `http://localhost:8080/api/v1/ai-ops/metrics/drilldown?service=${service}&window=5m`;
|
||||
const res = http.get(url, {
|
||||
headers: { 'Authorization': 'Bearer ${__ENV.AI_OPS_TOKEN}' },
|
||||
});
|
||||
|
||||
check(res, {
|
||||
'status is 200': (r) => r.status === 200,
|
||||
'response time < 3s': (r) => r.timings.duration < 3000,
|
||||
});
|
||||
|
||||
sleep(2);
|
||||
}
|
||||
Reference in New Issue
Block a user