┌─────────────────────────────────────────────────────────────┐
│ 用户层 │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 浏览器 (Vue 3 + Element Plus) │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
↓ HTTP/HTTPS
┌─────────────────────────────────────────────────────────────┐
│ 应用层 │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Flask 应用 (REST API) │ │
│ │ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │
│ │ │ 认证模块 │ │ 任务管理 │ │ 结果查询 │ │ │
│ │ └────────────┘ └────────────┘ └────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 业务层 │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 任务执行器 (Task Executor) │ │
│ │ ┌─────────────────┐ ┌─────────────────┐ │ │
│ │ │ PerfTestExecutor│ │QualityTestExecutor│ │ │
│ │ └─────────────────┘ └─────────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ 任务调度器 (APScheduler) │ │
│ └──────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 数据层 │
│ ┌────────────────┐ ┌────────────────┐ ┌──────────────┐ │
│ │ MySQL 数据库 │ │ 文件系统 │ │ 日志系统 │ │
│ └────────────────┘ └────────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ 外部工具 │
│ ┌────────────────┐ ┌────────────────┐ │
│ │ evalscope │ │ audit.py │ │
│ └────────────────┘ └────────────────┘ │
└─────────────────────────────────────────────────────────────┘
职责:用户身份验证和会话管理
实现:
- 使用 Flask-Login 进行 Session 认证
- 密码使用 Werkzeug 进行哈希加密
- 支持记住登录功能
流程:
用户登录 → 验证用户名密码 → 创建 Session → 返回用户信息
职责:任务的 CRUD 操作和调度管理
核心类:
Task:任务模型,存储任务配置和状态TaskExecutor:任务执行器,负责执行具体任务TaskScheduler:任务调度器,管理定时任务
任务生命周期:
创建 → 配置 → 启用 → 调度 → 执行 → 记录结果 → 禁用/删除
职责:执行具体的测试任务并解析结果
两种任务类型:
class PerfTestExecutor:
def execute(self, task):
# 1. 构建 evalscope perf 命令
cmd = self._build_command(task.config)
# 2. 执行命令
output = subprocess.run(cmd)
# 3. 解析输出
metrics = self._parse_output(output)
# 4. 保存结果
self._save_result(task, metrics, output)class QualityTestExecutor:
def execute(self, task):
# 1. 构建 audit.py 命令
cmd = self._build_command(task.config)
# 2. 执行命令
output = subprocess.run(cmd)
# 3. 解析 Risk Summary
risk_summary = self._parse_output(output)
# 4. 保存结果
self._save_result(task, risk_summary, output)职责:提供测试结果的查询和可视化数据
API 设计:
- 分页查询
- 时间范围筛选
- 任务筛选
- 图表数据聚合
┌──────────┐
│ 用户请求 │
└────┬─────┘
│
↓
┌──────────────┐
│ 任务路由 │
│ /api/tasks/ │
└────┬─────────┘
│
↓
┌──────────────┐
│ 验证参数 │
│ 创建任务对象 │
└────┬─────────┘
│
↓
┌──────────────┐
│ 保存到数据库 │
└────┬─────────┘
│
↓
┌──────────────┐
│ 添加到调度器 │
│ (如果启用) │
└────┬─────────┘
│
↓
┌──────────────┐
│ 返回任务信息 │
└──────────────┘
┌──────────────┐
│ 调度器触发 │
│ (Cron/Interval)│
└────┬─────────┘
│
↓
┌──────────────┐
│ 查询任务配置 │
└────┬─────────┘
│
↓
┌──────────────┐
│ 检查时间范围 │
└────┬─────────┘
│
↓
┌──────────────┐
│ 执行任务 │
│ (异步) │
└────┬─────────┘
│
↓
┌──────────────┐
│ 解析结果 │
└────┬─────────┘
│
↓
┌──────────────┐
│ 保存到数据库 │
│ 保存文件 │
└──────────────┘
┌──────────────┐
│ 前端请求 │
│ /api/results │
└────┬─────────┘
│
↓
┌──────────────┐
│ 验证参数 │
│ (分页、筛选) │
└────┬─────────┘
│
↓
┌──────────────┐
│ 查询数据库 │
│ (ORM) │
└────┬─────────┘
│
↓
┌──────────────┐
│ 数据转换 │
│ (JSON) │
└────┬─────────┘
│
↓
┌──────────────┐
│ 返回结果 │
└──────────────┘
App.vue
├── Login.vue (登录页)
└── Layout.vue (主布局)
├── Dashboard.vue (仪表盘)
├── Tasks.vue (任务管理)
├── PerfResults.vue (压力测试结果)
└── QualityResults.vue (质量测试结果)
使用 Vue 3 Composition API 的响应式系统:
// 任务列表状态
const tasks = ref([])
const loading = ref(false)
// 加载任务
const loadTasks = async () => {
loading.value = true
tasks.value = await taskAPI.getTasks()
loading.value = false
}使用 Axios 进行统一请求管理:
// 请求拦截器:添加认证头
api.interceptors.request.use(config => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
// 响应拦截器:统一错误处理
api.interceptors.response.use(
response => response.data,
error => {
if (error.response.status === 401) {
router.push('/login')
}
return Promise.reject(error)
}
)- 密码哈希存储(Werkzeug)
- Session 超时机制
- CSRF 保护(Flask-WTF)
- 使用 Flask-Login 的
@login_required装饰器 - 所有 API 都需要认证
- API Key 加密存储(可扩展)
- 敏感配置使用环境变量
- SQL 注入防护(ORM)
- 添加索引:
tasks(task_type, is_enabled)perf_test_results(task_id, execution_time)quality_test_results(task_id, execution_time)
- 分页查询
- 延迟加载关联数据
- 使用
joinedload预加载
- 使用 Redis 缓存任务状态(可扩展)
- 前端缓存图表数据
- 创建新的结果表模型
- 实现执行器类
- 注册到执行器工厂
- 添加前端配置表单
预留插件接口:
class TaskPlugin:
def execute(self, task):
raise NotImplementedError
def parse_output(self, output):
raise NotImplementedError预留 Webhook 接口:
def send_webhook(event, data):
# 任务完成、失败等事件通知
pass- 应用日志:
logs/app.log - 任务执行日志:
data/outputs/task_{id}/ - 日志轮转:RotatingFileHandler
- 记录任务执行时间
- 数据库查询性能
- API 响应时间
Nginx (反向代理)
↓
Gunicorn (应用服务器)
↓
Flask App
↓
MySQL
Load Balancer
↓
┌─────────────┬─────────────┐
│ Flask App 1 │ Flask App 2 │
└─────────────┴─────────────┘
↓ ↓
┌──────────────────────────┐
│ MySQL (主从复制) │
└──────────────────────────┘
↓
┌──────────────────────────┐
│ Redis (缓存/队列) │
└──────────────────────────┘
- 模型测试
- API 测试
- 解析器测试
- 任务执行流程测试
- 认证流程测试
- 前端交互测试
- 完整业务流程测试