feat: 完善系统配置审计通知功能并优化异常处理
- 新增异常处理体系(BaseException及其子类) - 优化密码、邮箱、用户名等基础类型 - 添加字典管理、登录日志、操作日志的E2E测试 - 完善API集成测试和安全测试 - 添加性能测试配置和脚本 - 优化OpenAPI配置和全局异常处理器
This commit is contained in:
+234
-183
@@ -1,246 +1,297 @@
|
||||
# 性能测试指南
|
||||
|
||||
## 测试目的
|
||||
## 概述
|
||||
|
||||
评估网关层对系统性能的影响,验证多模块架构下的性能表现。
|
||||
本目录包含Novalon管理系统的性能测试脚本,使用k6进行负载测试和压力测试。
|
||||
|
||||
## 测试工具
|
||||
## 前置条件
|
||||
|
||||
使用 k6 进行性能测试,支持以下测试场景:
|
||||
1. **后端服务运行**:
|
||||
```bash
|
||||
cd novalon-manage-api/manage-app
|
||||
mvn spring-boot:run
|
||||
```
|
||||
|
||||
### 1. 基准测试 (Baseline Test)
|
||||
- 持续负载:10个虚拟用户
|
||||
- 持续时间:30秒
|
||||
- 目的:建立性能基准
|
||||
2. **数据库服务运行**:
|
||||
```bash
|
||||
docker-compose up -d postgres
|
||||
```
|
||||
|
||||
### 2. 压力测试 (Stress Test)
|
||||
- 阶梯式负载:10 -> 50 -> 100 -> 50 -> 10
|
||||
- 持续时间:5分钟
|
||||
- 目的:测试系统在持续高负载下的表现
|
||||
3. **k6安装**:
|
||||
```bash
|
||||
# macOS
|
||||
brew install k6
|
||||
|
||||
### 3. 尖峰测试 (Spike Test)
|
||||
- 突发负载:10 -> 200 -> 10
|
||||
- 持续时间:70秒
|
||||
- 目的:测试系统应对突发流量的能力
|
||||
# Linux
|
||||
curl https://github.com/grafana/k6/releases/download/v0.50.0/k6-v0.50.0-linux-amd64.tar.gz -L | tar xvz
|
||||
sudo mv k6-v0.50.0-linux-amd64/k6 /usr/local/bin/
|
||||
```
|
||||
|
||||
## 运行测试
|
||||
## 测试场景
|
||||
|
||||
### 前置条件
|
||||
### 1. 基础性能测试
|
||||
|
||||
1. 启动所有服务:
|
||||
**目标**:测试系统在低负载下的性能表现
|
||||
|
||||
**虚拟用户数**:10
|
||||
**持续时间**:7分钟
|
||||
**测试接口**:健康检查、登录、用户列表
|
||||
|
||||
**运行命令**:
|
||||
```bash
|
||||
docker-compose up -d
|
||||
k6 run load_test.js
|
||||
```
|
||||
|
||||
2. 等待服务就绪:
|
||||
**预期结果**:
|
||||
- 95%的请求响应时间<500ms
|
||||
- 错误率<1%
|
||||
- 系统稳定运行
|
||||
|
||||
### 2. 中等负载测试
|
||||
|
||||
**目标**:测试系统在中负载下的性能表现
|
||||
|
||||
**虚拟用户数**:50
|
||||
**持续时间**:14分钟
|
||||
**测试接口**:健康检查、登录、用户列表、角色列表、字典列表
|
||||
|
||||
**运行命令**:
|
||||
```bash
|
||||
curl http://localhost:8080/actuator/health
|
||||
k6 run load_test.js
|
||||
```
|
||||
|
||||
### 运行基准测试
|
||||
**预期结果**:
|
||||
- 95%的请求响应时间<500ms
|
||||
- 错误率<1%
|
||||
- 系统稳定运行
|
||||
|
||||
### 3. 高负载测试
|
||||
|
||||
**目标**:测试系统在高负载下的性能表现
|
||||
|
||||
**虚拟用户数**:100
|
||||
**持续时间**:21分钟
|
||||
**测试接口**:健康检查、登录、用户列表、角色列表、字典列表、系统配置、通知列表、操作日志
|
||||
|
||||
**运行命令**:
|
||||
```bash
|
||||
k6 run performance_tests/gateway_performance_test.js \
|
||||
--env BASE_URL=http://localhost:8080 \
|
||||
--env DURATION=30s \
|
||||
--env VUS=10
|
||||
k6 run load_test.js
|
||||
```
|
||||
|
||||
### 运行压力测试
|
||||
**预期结果**:
|
||||
- 95%的请求响应时间<500ms
|
||||
- 99%的请求响应时间<1000ms
|
||||
- 错误率<1%
|
||||
- 系统稳定运行
|
||||
|
||||
### 4. 压力测试
|
||||
|
||||
**目标**:测试系统在极限负载下的性能表现
|
||||
|
||||
**虚拟用户数**:100
|
||||
**持续时间**:12分钟
|
||||
**测试接口**:所有主要接口
|
||||
|
||||
**运行命令**:
|
||||
```bash
|
||||
k6 run --config performance_tests/config.json \
|
||||
performance_tests/gateway_performance_test.js \
|
||||
--env BASE_URL=http://localhost:8080 \
|
||||
--scenario stress_test
|
||||
k6 run load_test.js
|
||||
```
|
||||
|
||||
### 运行尖峰测试
|
||||
|
||||
```bash
|
||||
k6 run --config performance_tests/config.json \
|
||||
performance_tests/gateway_performance_test.js \
|
||||
--env BASE_URL=http://localhost:8080 \
|
||||
--scenario spike_test
|
||||
```
|
||||
**预期结果**:
|
||||
- 识别系统性能瓶颈
|
||||
- 验证系统稳定性
|
||||
- 记录错误率
|
||||
|
||||
## 性能指标
|
||||
|
||||
### 关键指标
|
||||
|
||||
1. **响应时间 (Response Time)**
|
||||
- P50: 50%的请求响应时间
|
||||
- P95: 95%的请求响应时间
|
||||
- P99: 99%的请求响应时间
|
||||
- 目标:P95 < 500ms
|
||||
| 指标 | 描述 | 目标值 |
|
||||
|------|------|--------|
|
||||
| HTTP请求响应时间 | 请求从发送到接收的总时间 | p95<500ms, p99<1000ms |
|
||||
| HTTP请求失败率 | 失败请求占总请求的比例 | <1% |
|
||||
| HTTP请求速率 | 每秒处理的请求数 | >100请求/秒 |
|
||||
| 虚拟用户数 | 并发访问系统的用户数 | 根据测试场景 |
|
||||
| 吞吐量 | 系统每秒处理的请求数 | 根据测试场景 |
|
||||
|
||||
2. **吞吐量 (Throughput)**
|
||||
- RPS (Requests Per Second): 每秒请求数
|
||||
- 目标:根据业务需求设定
|
||||
### 性能阈值
|
||||
|
||||
3. **错误率 (Error Rate)**
|
||||
- HTTP 请求失败率
|
||||
- 目标:< 5%
|
||||
```javascript
|
||||
thresholds: {
|
||||
http_req_duration: ['p(95)<500'], // 95%的请求响应时间<500ms
|
||||
http_req_failed: ['rate<0.01'], // 错误率<1%
|
||||
}
|
||||
```
|
||||
|
||||
### 网关性能指标
|
||||
## 测试结果分析
|
||||
|
||||
1. **认证延迟**
|
||||
- JWT 验证时间
|
||||
- 目标:< 10ms
|
||||
### 查看测试结果
|
||||
|
||||
2. **授权延迟**
|
||||
- RBAC 权限检查时间
|
||||
- 目标:< 5ms
|
||||
k6会自动生成测试报告,包括:
|
||||
|
||||
3. **路由延迟**
|
||||
- 请求转发时间
|
||||
- 目标:< 20ms
|
||||
1. **控制台输出**:实时显示测试进度和结果
|
||||
2. **HTML报告**:使用`--out`参数生成HTML报告
|
||||
3. **JSON报告**:使用`--out`参数生成JSON报告
|
||||
|
||||
## 性能基准
|
||||
### 生成HTML报告
|
||||
|
||||
### 无网关架构
|
||||
- 平均响应时间:~200ms
|
||||
- P95 响应时间:~350ms
|
||||
- 吞吐量:~500 RPS
|
||||
```bash
|
||||
k6 run --out html=report.html load_test.js
|
||||
open report.html
|
||||
```
|
||||
|
||||
### 有网关架构(预期)
|
||||
- 平均响应时间:~220ms (+10%)
|
||||
- P95 响应时间:~400ms (+14%)
|
||||
- 吞吐量:~450 RPS (-10%)
|
||||
### 生成JSON报告
|
||||
|
||||
### 性能影响评估
|
||||
|
||||
网关层预期性能开销:
|
||||
- 响应时间增加:10-15%
|
||||
- 吞吐量下降:10-15%
|
||||
- CPU 使用增加:5-10%
|
||||
```bash
|
||||
k6 run --out json=report.json load_test.js
|
||||
```
|
||||
|
||||
## 性能优化建议
|
||||
|
||||
### 网关层优化
|
||||
### 1. 数据库优化
|
||||
|
||||
1. **缓存优化**
|
||||
- JWT Token 缓存
|
||||
- 权限规则缓存
|
||||
- 路由规则缓存
|
||||
- 添加适当的索引
|
||||
- 优化慢查询
|
||||
- 使用连接池
|
||||
- 考虑读写分离
|
||||
|
||||
2. **连接池优化**
|
||||
- HTTP 客户端连接池
|
||||
- 数据库连接池
|
||||
### 2. 缓存优化
|
||||
|
||||
3. **异步处理**
|
||||
- 非阻塞 I/O
|
||||
- 响应式编程
|
||||
- 使用Redis缓存热点数据
|
||||
- 实现查询结果缓存
|
||||
- 使用CDN缓存静态资源
|
||||
|
||||
### 应用层优化
|
||||
### 3. 应用优化
|
||||
|
||||
1. **数据库优化**
|
||||
- 索引优化
|
||||
- 查询优化
|
||||
- 连接池配置
|
||||
- 优化算法复杂度
|
||||
- 减少不必要的数据库查询
|
||||
- 使用异步处理
|
||||
- 实现请求合并
|
||||
|
||||
2. **缓存策略**
|
||||
- Redis 缓存
|
||||
- 本地缓存
|
||||
### 4. 基础设施优化
|
||||
|
||||
3. **代码优化**
|
||||
- 减少序列化开销
|
||||
- 优化算法复杂度
|
||||
|
||||
## 监控指标
|
||||
|
||||
使用 Spring Boot Actuator 进行轻量级监控:
|
||||
|
||||
### 健康检查
|
||||
```bash
|
||||
curl http://localhost:8080/actuator/health
|
||||
```
|
||||
|
||||
### 应用信息
|
||||
```bash
|
||||
curl http://localhost:8080/actuator/info
|
||||
```
|
||||
|
||||
### 性能指标
|
||||
```bash
|
||||
curl http://localhost:8080/actuator/metrics
|
||||
```
|
||||
|
||||
### 系统指标
|
||||
- JVM 内存使用
|
||||
- GC 频率和时间
|
||||
- 线程池使用情况
|
||||
- HTTP 请求统计
|
||||
|
||||
## 结果分析
|
||||
|
||||
### 性能报告模板
|
||||
|
||||
```
|
||||
测试场景:[基准测试/压力测试/尖峰测试]
|
||||
测试时间:[YYYY-MM-DD HH:MM:SS]
|
||||
测试时长:[XX秒]
|
||||
虚拟用户数:[XX]
|
||||
|
||||
性能指标:
|
||||
- 平均响应时间:[XXms]
|
||||
- P95 响应时间:[XXms]
|
||||
- P99 响应时间:[XXms]
|
||||
- 吞吐量:[XX RPS]
|
||||
- 错误率:[XX%]
|
||||
|
||||
网关性能:
|
||||
- 认证延迟:[XXms]
|
||||
- 授权延迟:[XXms]
|
||||
- 路由延迟:[XXms]
|
||||
|
||||
系统资源:
|
||||
- CPU 使用率:[XX%]
|
||||
- 内存使用率:[XX%]
|
||||
|
||||
结论:
|
||||
[性能是否满足要求,是否需要优化]
|
||||
```
|
||||
- 使用负载均衡
|
||||
- 水平扩展应用实例
|
||||
- 优化网络配置
|
||||
- 使用更快的硬件
|
||||
|
||||
## 故障排查
|
||||
|
||||
### 常见问题
|
||||
### 问题1:连接超时
|
||||
|
||||
1. **连接拒绝**
|
||||
- 检查服务是否启动
|
||||
- 检查端口是否正确
|
||||
- 检查防火墙设置
|
||||
**症状**:大量请求失败,错误率高
|
||||
|
||||
2. **高错误率**
|
||||
- 检查日志文件
|
||||
- 检查数据库连接
|
||||
- 检查内存使用情况
|
||||
**解决方案**:
|
||||
- 检查后端服务是否正常运行
|
||||
- 检查数据库连接是否正常
|
||||
- 增加连接池大小
|
||||
- 优化数据库查询
|
||||
|
||||
3. **响应时间过长**
|
||||
- 检查慢查询日志
|
||||
- 检查网络延迟
|
||||
- 检查 GC 情况
|
||||
### 问题2:响应时间过长
|
||||
|
||||
## 持续集成
|
||||
**症状**:95%或99%的请求响应时间超过阈值
|
||||
|
||||
将性能测试集成到 Woodpecker CI:
|
||||
**解决方案**:
|
||||
- 分析慢查询日志
|
||||
- 添加数据库索引
|
||||
- 优化应用逻辑
|
||||
- 增加缓存
|
||||
|
||||
### 问题3:内存溢出
|
||||
|
||||
**症状**:应用崩溃或性能急剧下降
|
||||
|
||||
**解决方案**:
|
||||
- 增加JVM堆内存
|
||||
- 分析内存泄漏
|
||||
- 优化对象创建
|
||||
- 使用对象池
|
||||
|
||||
## CI/CD集成
|
||||
|
||||
### GitHub Actions示例
|
||||
|
||||
```yaml
|
||||
performance_test:
|
||||
image: python:3.13
|
||||
commands:
|
||||
- cd api_integration_tests
|
||||
- pip install -r requirements.txt
|
||||
- pytest tests/test_real_e2e.py -v --no-cov
|
||||
depends_on:
|
||||
- deploy-staging
|
||||
when:
|
||||
- event: push
|
||||
branch: develop
|
||||
name: Performance Tests
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 2 * * *' # 每天凌晨2点运行
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
performance-test:
|
||||
runs-on: ubuntu-latest
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:15
|
||||
env:
|
||||
POSTGRES_DB: manage_system
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
ports:
|
||||
- 55432:5432
|
||||
options: >-
|
||||
--health-cmd pg_isready
|
||||
--health-interval 10s
|
||||
--health-timeout 5s
|
||||
--health-retries 5
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Set up Java
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Build backend
|
||||
run: |
|
||||
cd novalon-manage-api
|
||||
mvn clean package -DskipTests
|
||||
|
||||
- name: Start backend
|
||||
run: |
|
||||
cd novalon-manage-api/manage-app
|
||||
java -jar target/manage-app-1.0.0.jar &
|
||||
sleep 30
|
||||
|
||||
- name: Install k6
|
||||
run: |
|
||||
curl https://github.com/grafana/k6/releases/download/v0.50.0/k6-v0.50.0-linux-amd64.tar.gz -L | tar xvz
|
||||
sudo mv k6-v0.50.0-linux-amd64/k6 /usr/local/bin/
|
||||
|
||||
- name: Run performance tests
|
||||
run: |
|
||||
cd performance_tests
|
||||
k6 run --out json=performance-results.json load_test.js
|
||||
|
||||
- name: Upload performance results
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: performance-results
|
||||
path: performance_tests/performance-results.json
|
||||
```
|
||||
|
||||
## 参考资料
|
||||
## 最佳实践
|
||||
|
||||
- [k6 官方文档](https://k6.io/docs/)
|
||||
- [Spring Boot Actuator 文档](https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html)
|
||||
- [Spring WebFlux 性能优化](https://docs.spring.io/spring-framework/reference/web/webflux/reactive-spring.html)
|
||||
1. **在非生产环境运行**:性能测试应该在测试环境或预发布环境运行
|
||||
2. **使用真实数据**:使用与生产环境相似的数据量和数据分布
|
||||
3. **监控系统资源**:在测试过程中监控CPU、内存、磁盘、网络使用情况
|
||||
4. **多次运行**:多次运行测试以获得稳定的结果
|
||||
5. **记录基准**:建立性能基准,便于比较和改进
|
||||
6. **分析瓶颈**:根据测试结果分析性能瓶颈并优化
|
||||
7. **持续优化**:将性能测试集成到CI/CD流水线,持续监控和优化
|
||||
|
||||
## 联系方式
|
||||
|
||||
如有问题或建议,请联系:
|
||||
- **作者**:张翔
|
||||
- **角色**:全栈质量保障与研发效能工程师
|
||||
- **项目**:Novalon管理系统
|
||||
|
||||
---
|
||||
|
||||
**文档版本**:1.0
|
||||
**最后更新**:2026-03-24
|
||||
|
||||
+148
-30
@@ -1,36 +1,154 @@
|
||||
{
|
||||
"scenarios": {
|
||||
"baseline": {
|
||||
"executor": "constant-vus",
|
||||
"vus": 10,
|
||||
"duration": "30s"
|
||||
"name": "Novalon管理系统性能测试",
|
||||
"stages": [
|
||||
{
|
||||
"name": "预热阶段",
|
||||
"duration": "2m",
|
||||
"target": 10,
|
||||
"description": "2分钟内增加到10个虚拟用户"
|
||||
},
|
||||
"stress_test": {
|
||||
"executor": "ramping-vus",
|
||||
"startVUs": 10,
|
||||
"stages": [
|
||||
{ "duration": "1m", "target": 50 },
|
||||
{ "duration": "2m", "target": 100 },
|
||||
{ "duration": "1m", "target": 50 },
|
||||
{ "duration": "1m", "target": 10 }
|
||||
]
|
||||
{
|
||||
"name": "稳定阶段1",
|
||||
"duration": "5m",
|
||||
"target": 10,
|
||||
"description": "保持10个虚拟用户5分钟"
|
||||
},
|
||||
"spike_test": {
|
||||
"executor": "ramping-vus",
|
||||
"startVUs": 10,
|
||||
"stages": [
|
||||
{ "duration": "30s", "target": 10 },
|
||||
{ "duration": "10s", "target": 200 },
|
||||
{ "duration": "30s", "target": 10 }
|
||||
]
|
||||
{
|
||||
"name": "负载增加阶段",
|
||||
"duration": "2m",
|
||||
"target": 50,
|
||||
"description": "2分钟内增加到50个虚拟用户"
|
||||
},
|
||||
{
|
||||
"name": "稳定阶段2",
|
||||
"duration": "5m",
|
||||
"target": 50,
|
||||
"description": "保持50个虚拟用户5分钟"
|
||||
},
|
||||
{
|
||||
"name": "高负载阶段",
|
||||
"duration": "2m",
|
||||
"target": 100,
|
||||
"description": "2分钟内增加到100个虚拟用户"
|
||||
},
|
||||
{
|
||||
"name": "稳定阶段3",
|
||||
"duration": "5m",
|
||||
"target": 100,
|
||||
"description": "保持100个虚拟用户5分钟"
|
||||
},
|
||||
{
|
||||
"name": "冷却阶段",
|
||||
"duration": "2m",
|
||||
"target": 0,
|
||||
"description": "2分钟内降到0个虚拟用户"
|
||||
}
|
||||
],
|
||||
"thresholds": {
|
||||
"http_req_duration": {
|
||||
"p95": "<500",
|
||||
"p99": "<1000",
|
||||
"description": "95%的请求响应时间<500ms,99%的请求响应时间<1000ms"
|
||||
},
|
||||
"http_req_failed": {
|
||||
"rate": "<0.01",
|
||||
"description": "错误率<1%"
|
||||
},
|
||||
"http_reqs": {
|
||||
"rate": ">100",
|
||||
"description": "请求速率>100请求/秒"
|
||||
}
|
||||
},
|
||||
"thresholds": {
|
||||
"http_req_duration": [
|
||||
{ "target": "p(95)<500", "abortOnFail": true }
|
||||
],
|
||||
"http_req_failed": [
|
||||
{ "target": "rate<0.05", "abortOnFail": true }
|
||||
]
|
||||
"endpoints": [
|
||||
{
|
||||
"name": "健康检查",
|
||||
"method": "GET",
|
||||
"path": "/actuator/health",
|
||||
"expected_status": 200,
|
||||
"max_duration": 100,
|
||||
"description": "后端健康检查接口"
|
||||
},
|
||||
{
|
||||
"name": "登录",
|
||||
"method": "POST",
|
||||
"path": "/api/auth/login",
|
||||
"expected_status": 200,
|
||||
"max_duration": 500,
|
||||
"description": "用户登录接口"
|
||||
},
|
||||
{
|
||||
"name": "用户列表",
|
||||
"method": "GET",
|
||||
"path": "/api/users?page=0&size=10",
|
||||
"expected_status": 200,
|
||||
"max_duration": 300,
|
||||
"description": "获取用户列表接口"
|
||||
},
|
||||
{
|
||||
"name": "角色列表",
|
||||
"method": "GET",
|
||||
"path": "/api/roles?page=0&size=10",
|
||||
"expected_status": 200,
|
||||
"max_duration": 300,
|
||||
"description": "获取角色列表接口"
|
||||
},
|
||||
{
|
||||
"name": "字典列表",
|
||||
"method": "GET",
|
||||
"path": "/api/dicts?page=0&size=10",
|
||||
"expected_status": 200,
|
||||
"max_duration": 300,
|
||||
"description": "获取字典列表接口"
|
||||
},
|
||||
{
|
||||
"name": "系统配置",
|
||||
"method": "GET",
|
||||
"path": "/api/configs?page=0&size=10",
|
||||
"expected_status": 200,
|
||||
"max_duration": 300,
|
||||
"description": "获取系统配置接口"
|
||||
},
|
||||
{
|
||||
"name": "通知列表",
|
||||
"method": "GET",
|
||||
"path": "/api/notices?page=0&size=10",
|
||||
"expected_status": 200,
|
||||
"max_duration": 300,
|
||||
"description": "获取通知列表接口"
|
||||
},
|
||||
{
|
||||
"name": "操作日志",
|
||||
"method": "GET",
|
||||
"path": "/api/operation-logs?page=0&size=10",
|
||||
"expected_status": 200,
|
||||
"max_duration": 300,
|
||||
"description": "获取操作日志接口"
|
||||
}
|
||||
],
|
||||
"scenarios": {
|
||||
"basic": {
|
||||
"name": "基础性能测试",
|
||||
"description": "测试系统在低负载下的性能表现",
|
||||
"stages": ["预热阶段", "稳定阶段1", "冷却阶段"],
|
||||
"endpoints": ["健康检查", "登录", "用户列表"]
|
||||
},
|
||||
"moderate": {
|
||||
"name": "中等负载测试",
|
||||
"description": "测试系统在中负载下的性能表现",
|
||||
"stages": ["预热阶段", "稳定阶段1", "负载增加阶段", "稳定阶段2", "冷却阶段"],
|
||||
"endpoints": ["健康检查", "登录", "用户列表", "角色列表", "字典列表"]
|
||||
},
|
||||
"high": {
|
||||
"name": "高负载测试",
|
||||
"description": "测试系统在高负载下的性能表现",
|
||||
"stages": ["预热阶段", "稳定阶段1", "负载增加阶段", "稳定阶段2", "高负载阶段", "稳定阶段3", "冷却阶段"],
|
||||
"endpoints": ["健康检查", "登录", "用户列表", "角色列表", "字典列表", "系统配置", "通知列表", "操作日志"]
|
||||
},
|
||||
"stress": {
|
||||
"name": "压力测试",
|
||||
"description": "测试系统在极限负载下的性能表现",
|
||||
"stages": ["高负载阶段", "稳定阶段3", "冷却阶段"],
|
||||
"endpoints": ["健康检查", "登录", "用户列表", "角色列表", "字典列表", "系统配置", "通知列表", "操作日志"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
import http from 'k6/http';
|
||||
import { check, sleep } from 'k6';
|
||||
|
||||
const BASE_URL = 'http://localhost:8084';
|
||||
|
||||
export const options = {
|
||||
stages: [
|
||||
{ duration: '2m', target: 10 }, // 2分钟内增加到10用户
|
||||
{ duration: '5m', target: 10 }, // 保持10用户5分钟
|
||||
{ duration: '2m', target: 50 }, // 2分钟内增加到50用户
|
||||
{ duration: '5m', target: 50 }, // 保持50用户5分钟
|
||||
{ duration: '2m', target: 100 }, // 2分钟内增加到100用户
|
||||
{ duration: '5m', target: 100 }, // 保持100用户5分钟
|
||||
{ duration: '2m', target: 0 }, // 2分钟内降到0用户
|
||||
],
|
||||
thresholds: {
|
||||
http_req_duration: ['p(95)<500'], // 95%的请求响应时间<500ms
|
||||
http_req_failed: ['rate<0.01'], // 错误率<1%
|
||||
},
|
||||
};
|
||||
|
||||
export default function () {
|
||||
// 测试1: 健康检查
|
||||
let healthRes = http.get(`${BASE_URL}/actuator/health`);
|
||||
check(healthRes, {
|
||||
'健康检查状态码200': (r) => r.status === 200,
|
||||
'健康检查响应时间<100ms': (r) => r.timings.duration < 100,
|
||||
});
|
||||
|
||||
// 测试2: 登录
|
||||
let loginRes = http.post(
|
||||
`${BASE_URL}/api/auth/login`,
|
||||
JSON.stringify({
|
||||
username: 'admin',
|
||||
password: 'admin123',
|
||||
}),
|
||||
{
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
}
|
||||
);
|
||||
check(loginRes, {
|
||||
'登录状态码200': (r) => r.status === 200,
|
||||
'登录响应时间<500ms': (r) => r.timings.duration < 500,
|
||||
'登录返回token': (r) => JSON.parse(r.body).token !== undefined,
|
||||
});
|
||||
|
||||
// 测试3: 获取用户列表
|
||||
const token = JSON.parse(loginRes.body).token;
|
||||
let usersRes = http.get(
|
||||
`${BASE_URL}/api/users?page=0&size=10`,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
check(usersRes, {
|
||||
'用户列表状态码200': (r) => r.status === 200,
|
||||
'用户列表响应时间<300ms': (r) => r.timings.duration < 300,
|
||||
'用户列表返回数据': (r) => JSON.parse(r.body).content !== undefined,
|
||||
});
|
||||
|
||||
// 测试4: 获取角色列表
|
||||
let rolesRes = http.get(
|
||||
`${BASE_URL}/api/roles?page=0&size=10`,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
check(rolesRes, {
|
||||
'角色列表状态码200': (r) => r.status === 200,
|
||||
'角色列表响应时间<300ms': (r) => r.timings.duration < 300,
|
||||
'角色列表返回数据': (r) => JSON.parse(r.body).content !== undefined,
|
||||
});
|
||||
|
||||
// 测试5: 获取字典列表
|
||||
let dictRes = http.get(
|
||||
`${BASE_URL}/api/dicts?page=0&size=10`,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
check(dictRes, {
|
||||
'字典列表状态码200': (r) => r.status === 200,
|
||||
'字典列表响应时间<300ms': (r) => r.timings.duration < 300,
|
||||
'字典列表返回数据': (r) => JSON.parse(r.body).content !== undefined,
|
||||
});
|
||||
|
||||
// 测试6: 获取系统配置
|
||||
let configRes = http.get(
|
||||
`${BASE_URL}/api/configs?page=0&size=10`,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
check(configRes, {
|
||||
'系统配置状态码200': (r) => r.status === 200,
|
||||
'系统配置响应时间<300ms': (r) => r.timings.duration < 300,
|
||||
'系统配置返回数据': (r) => JSON.parse(r.body).content !== undefined,
|
||||
});
|
||||
|
||||
// 测试7: 获取通知列表
|
||||
let noticeRes = http.get(
|
||||
`${BASE_URL}/api/notices?page=0&size=10`,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
check(noticeRes, {
|
||||
'通知列表状态码200': (r) => r.status === 200,
|
||||
'通知列表响应时间<300ms': (r) => r.timings.duration < 300,
|
||||
'通知列表返回数据': (r) => JSON.parse(r.body).content !== undefined,
|
||||
});
|
||||
|
||||
// 测试8: 获取操作日志
|
||||
let opLogRes = http.get(
|
||||
`${BASE_URL}/api/operation-logs?page=0&size=10`,
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${token}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
check(opLogRes, {
|
||||
'操作日志状态码200': (r) => r.status === 200,
|
||||
'操作日志响应时间<300ms': (r) => r.timings.duration < 300,
|
||||
'操作日志返回数据': (r) => JSON.parse(r.body).content !== undefined,
|
||||
});
|
||||
|
||||
sleep(1); // 每个虚拟用户之间间隔1秒
|
||||
}
|
||||
Reference in New Issue
Block a user