PERF_TEST_PLAN.md 5.9 KB

压测用例与验收阈值(MySQL 版本)

适用范围:当前版本服务端(Flask + MySQL),包含 Gogs 外部依赖与资源下载(zip 流式响应)。

1. 目标与原则

  • 目标:在峰值并发 500 的前提下,给出可复用的压测用例与“商业化验收”阈值。
  • 原则:
    • 测试结果必须可复现:固定部署方式、固定数据库与 Gogs 网络条件、固定数据规模。
    • “预期 4xx”不计入错误率:如未登录预览被 401、非 VIP 下载被 403;错误率统计非预期 4xx + 5xx + 网络/超时错误。
    • Debug 模式禁止用于压测:必须关闭 Debug,使用生产 WSGI(例如 Nginx+Gunicorn/Waitress)。

2. 接口分层(用于设定不同阈值)

按调用链复杂度分 3 类:

  • A 类(纯 DB / 轻接口):/me、/plans、/resources、/resources/{id}、/orders
  • B 类(DB + Gogs 外部依赖):/resources/{id}/repo/refs、/repo/tree、/repo/file、/repo/commits、/repo/readme
  • C 类(重流量下载):POST /resources/{id}/download(写 download_logs + 拉取/生成 zip 并流式返回)

接口定义位置参考:server/routes.py

3. 测试前置(必须满足)

  • 服务端:
    • Debug=off
    • 生产 WSGI:多 worker(压测报告必须记录 worker/threads 配置)
  • 数据库:
    • MySQL 已切换为主库
    • 记录 MySQL 版本、max_connections、slow_query_log 开启情况
  • Gogs:
    • 记录 base_url、网络位置(同机房/公网)、是否走代理
    • 选定 1~3 个稳定仓库用于 repo 接口压测(包含 README 与若干目录/文件)
  • 数据规模(建议最低):
    • resources:>= 200
    • users:>= 100
    • download_logs:>= 1000

4. 用例矩阵(必须执行的 5 组)

用例 1:Smoke(上线前冒烟)

  • 并发:10
  • 时长:5 分钟
  • 目标:0 非预期 5xx;关键接口延迟稳定;无数据库连接池相关报错

用例 2:Baseline(日常稳定基线)

  • 并发:50
  • 时长:20 分钟
  • 目标:形成基线;观察 MySQL 连接数与慢查询;为后续优化提供对比

用例 3:Peak(峰值验收)

  • 并发:ramp 到 500(建议 5 分钟爬升)+ 稳态 10 分钟
  • 目标:满足第 6 节的验收阈值(p95/p99/错误率)

用例 4:Soak(稳定性/泄漏)

  • 并发:200
  • 时长:60–120 分钟
  • 目标:错误率不爬升;内存不持续增长;MySQL 连接不泄漏;Gogs 不被打爆

用例 5:依赖故障(Gogs 降级验收)

  • 方法:让 Gogs 延迟显著升高/偶发 5xx/不可达(或压测端注入超时)
  • 目标:
    • A 类接口仍达标
    • B 类接口错误可控且返回明确错误码
    • 服务不雪崩(错误率不随着时间持续上升)

5. 流量模型(按真实路径建议)

并发 500 建议拆两类虚拟用户(VU)并行跑,比例可按实际调整:

场景 S1:游客浏览(60% VU)

  • GET /resources(35%)
  • GET /resources/{id}(20%)
  • GET /resources/{id}/repo/tree(15%)
  • GET /resources/{id}/repo/file(10%,其中一部分应预期 401)
  • GET /resources/{id}/repo/readme(10%)
  • GET /me(10%)

场景 S2:登录用户浏览 + 下载(40% VU)

  • POST /auth/login(每个 VU 启动时 1 次)
  • GET /resources、/resources/{id}、/repo/tree、/repo/refs(同上但比例略降)
  • POST /resources/{id}/download(3%–8%,建议从 3% 开始)
  • POST /orders(可选 1%)+ GET /orders(可选 2%)

6. 验收阈值(商业化标准)

6.1 全局阈值(所有用例共同)

  • 非预期错误率:< 0.1%(按请求数口径)
  • 5xx:Peak/Soak 用例中 = 0
  • 超时/网络错误:< 0.05%
  • 稳定性:无进程崩溃/重启;Soak 期间无持续线性内存增长

6.2 A 类接口(纯 DB / 轻接口)

目标:95 线 < 300ms(并按接口细化)

  • GET /me:p95 < 120ms;p99 < 250ms
  • GET /plans:p95 < 150ms;p99 < 300ms
  • GET /resources(pageSize=12/20):p95 < 250ms;p99 < 450ms
  • GET /resources/{id}:p95 < 200ms;p99 < 350ms
  • POST /auth/login:p95 < 250ms;p99 < 450ms

6.3 B 类接口(DB + Gogs 外部依赖)

说明:外部依赖主导,阈值放宽但要求稳定与可解释错误。

  • GET /resources/{id}/repo/refs:p95 < 900ms;p99 < 1500ms;错误率(依赖 502)< 0.5%
  • GET /resources/{id}/repo/tree:p95 < 900ms;p99 < 1500ms;错误率 < 0.5%
  • GET /resources/{id}/repo/file(小文件预览):p95 < 1000ms;p99 < 2000ms
  • GET /resources/{id}/repo/commits:p95 < 1000ms;p99 < 2000ms
  • GET /resources/{id}/repo/readme:p95 < 900ms;p99 < 1500ms

6.4 C 类接口(下载)

下载不建议用“完整下载耗时 p95”作为唯一指标,拆分两段:

  • POST /resources/{id}/download:
    • 首包时间(TTFB):p95 < 1500ms;p99 < 3000ms
    • 失败率:< 0.2%
    • 正确性:zip 可解压,内容抽样一致(抽样 >= 20 次)

7. 系统侧观测(必须记录)

  • MySQL:
    • 峰值活跃连接数不超过 max_connections 的 70%
    • slow_query_log 中慢查询占比 < 1%(Peak/Soak)
    • 无持续锁等待堆积(重点关注 orders、download_logs 写入)
  • 应用:
    • CPU:Peak 稳态平均 < 70%(留余量)
    • 内存:Soak 期间无持续线性增长
    • 日志:无大量数据库断连/重连异常
  • Gogs:
    • 记录依赖接口失败率与平均耗时;出现异常时是否触发错误放大

8. 报告模板(建议每次压测统一填写)

  • 版本信息:commit/构建号、环境(Windows/Linux)、WSGI 方案与参数(workers/threads)
  • 数据库:MySQL 版本、连接池参数、max_connections、慢查询配置
  • Gogs:base_url、网络环境、选定 repo 列表
  • 用例:Smoke/Baseline/Peak/Soak/依赖故障 的并发、时长、流量配比
  • 结果(按接口分层给出):
    • A 类:p50/p95/p99、吞吐、非预期错误率
    • B 类:p50/p95/p99、依赖 502 占比、失败原因 TopN
    • C 类:TTFB p95/p99、失败率、平均吞吐、正确性抽样结果