Files
gongxue-base/docs/refactor/performance-benchmark-summary-20260630.md
2026-07-01 03:01:02 +08:00

115 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 真实迁移数据 API 压测摘要
更新时间2026-07-01
这份文件只记录脱敏后的聚合指标,便于 README、上线门禁和后续 AI 开发继续引用。原始 JSON/Markdown 报告位于已忽略的 `docs/refactor/performance-reports/`,不要提交到 Git。
## 测试口径
- 环境:本地 Docker Desktop + 本地 Supabase/PostgreSQL + 本地 API 进程。
- 数据PocketBase 真实导出数据导入新 PostgreSQL 后压测。
- 数据规模:当前真实迁移库已包含前期压测写入记录,约 74,117 道题、1,601 个题目合集、3,106 个练习蓝图、3,505 个单词、2,678 条知识手册、3,690 个用户、196,846 条答题记录、38,207 条错题和 466 条权益。
- Docker Desktop 资源:当前本机约 20 CPU、62.7GB 内存,高于常见 4 核 16G 云服务器;本地结果只用于观察代码和索引趋势。
- 写入流量:混合场景开启真实刷题闭环,包含创建 session、拉取 session detail、提交若干答案、交卷和读取报告。
- 商城说明:本地库的订单数据会受 seed、烟测和导入演练影响当前容量结论聚焦题库读写链路不用于推断 GMV、支付或订单峰值。
- 排行榜:未纳入默认压测,当前产品默认关闭排行榜。
- 说明:压测 worker 是无停顿请求流,不等同于真实在线学生数。真实在线容量需要前端埋点后按单个学生平均 RPS 折算。
## 结果
### 120 秒阶梯基线
| 并发 worker | 时长 | 刷题写入比例 | 请求数 | 错误率 | 吞吐 | P95 | P99 |
| ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
| 30 | 120s | 10% | 112,896 | 0.00% | 934.74 req/s | 64.26 ms | 81.14 ms |
| 50 | 120s | 10% | 92,737 | 0.00% | 767.24 req/s | 121.51 ms | 159.12 ms |
| 100 | 120s | 8% | 84,608 | 0.00% | 699.27 req/s | 254.69 ms | 331.84 ms |
| 150 | 120s | 6% | 82,693 | 0.00% | 682.40 req/s | 369.90 ms | 493.69 ms |
### 60 秒复测快照
2026-06-30 晚重新 `supabase db reset`、导入同一批 PocketBase 真实 JSON 后复跑,`pb:import:validate` 为 0 failures/3 warnings`pb:import:sample` 为 0 failures/6 warnings/1 skipped/39 passed。
| 并发 worker | 时长 | 刷题写入比例 | 请求数 | 错误率 | 吞吐 | P95 | P99 |
| ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
| 30 | 60s | 10% | 64,025 | 0.00% | 1052.52 req/s | 55.14 ms | 70.15 ms |
| 100 | 60s | 8% | 59,123 | 0.00% | 969.92 req/s | 179.70 ms | 235.19 ms |
| 150 | 60s | 6% | 53,167 | 0.00% | 870.06 req/s | 298.23 ms | 402.89 ms |
### 2026-07-01 上线门禁与读写复核
这轮在同一套本地 Docker/Supabase 真实迁移库上执行,补充了只读上线门禁和 50 worker 混合读写复核。
| 并发 worker | 时长 | 刷题写入比例 | 请求数 | 错误率 | 吞吐 | P95 | P99 | 结论 |
| ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | --- |
| 30 | 120s | 0% | 108,336 | 0.00% | 897.04 req/s | 68.32 ms | 84.50 ms | 通过只读上线门禁 |
| 50 | 60s | 10% | 52,979 | 0.00% | 870.42 req/s | 104.92 ms | 136.22 ms | 通过混合读写观察线 |
### 2026-07-01 H5 发布烟测后读写复核
本轮在新增 `npm run smoke:taro:h5` 后复跑,确认后端真实数据读写容量未受前端发布守卫改动影响。压测仍使用本地 Docker/Supabase 真实迁移库,排行榜未纳入默认负载。
| 并发 worker | 时长 | 刷题写入比例 | 请求数 | 错误率 | 吞吐 | P95 | P99 | 结论 |
| ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | --- |
| 50 | 60s | 10% | 51,425 | 0.00% | 845.06 req/s | 110.39 ms | 138.79 ms | 通过混合读写观察线 |
| 100 | 60s | 8% | 51,103 | 0.00% | 838.42 req/s | 210.07 ms | 272.15 ms | 本地舒适区内 |
| 150 | 60s | 6% | 44,889 | 0.00% | 735.22 req/s | 357.74 ms | 469.28 ms | 零错误但接近本机压力上沿 |
同轮 `npm run smoke:launch-persona` 已通过,覆盖普通学生 SVIP 后刷题、收藏、错题复习入口,租户管理员 dashboard/主题/学生/销售转化入口,平台管理员租户/套餐/审计入口,以及学生越权后台和跨租户访问拒绝。
同轮 `npm run perf:postgres:evidence` 运行成功,但本地默认 PostgreSQL 仍有生产前必须调优的 warning`jit=on``statement_timeout=0``idle_in_transaction_session_timeout=0``lock_timeout=0`。上云后要按 `docs/refactor/postgresql-4c16g-tuning.md` 调整并重启需要重启的参数,再复跑证据采集和压测。
### 2026-07-01 API 契约门禁后读写复核
本轮在新增 `node scripts/taro-api-contract-test.js` 并纳入 `npm run test:readiness` 后复跑,确认前端接口契约守卫不会影响后端真实数据刷题读写容量。压测仍使用本地 Docker/Supabase 真实迁移库,排行榜未纳入默认负载。
| 并发 worker | 时长 | 刷题写入比例 | 请求数 | 错误率 | 吞吐 | P95 | P99 | 结论 |
| ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | --- |
| 100 | 60s | 8% | 43,379 | 0.00% | 710.38 req/s | 257.59 ms | 328.75 ms | 通过 100 worker 舒适区门槛 |
| 150 | 60s | 6% | 43,738 | 0.00% | 716.06 req/s | 375.03 ms | 485.60 ms | 零错误但进入压力区 |
同轮 `npm run perf:summary -- --allow-writes` 已分别通过 100 worker `P95 <= 300ms/P99 <= 800ms` 和 150 worker `P95 <= 500ms/P99 <= 1200ms` 的容量观察阈值150 worker 不建议作为当前本机 Docker 日常舒适区。
### 2026-07-01 Taro 角色旅程契约后读写复核
本轮在新增 `node scripts/taro-persona-contract-test.js` 并纳入 `npm run test:readiness` 后复跑,确认前端角色旅程契约守卫不会影响后端真实数据刷题读写容量。压测仍使用本地 Docker/Supabase 真实迁移库,排行榜未纳入默认负载。
| 并发 worker | 时长 | 刷题写入比例 | 请求数 | 错误率 | 吞吐 | P95 | P99 | 结论 |
| ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | --- |
| 100 | 60s | 8% | 45,047 | 0.00% | 737.22 req/s | 244.12 ms | 320.26 ms | 通过 100 worker 舒适区门槛 |
| 150 | 60s | 6% | 41,707 | 0.00% | 681.44 req/s | 387.58 ms | 510.79 ms | 零错误但进入压力区 |
同轮 `npm run perf:summary -- --allow-writes` 已分别通过 100 worker `P95 <= 300ms/P99 <= 800ms` 和 150 worker `P95 <= 500ms/P99 <= 1200ms` 的容量观察阈值。
### 2026-07-01 最新真实数据容量复核
本轮按用户最新要求重新确认本地 Supabase 数据量、Docker Desktop 资源,并复跑只读上线门禁与 50/100/150 混合读写阶梯。排行榜仍未纳入默认负载,头像相关链路不参与压测,因为学生头像产品策略已固定为男女预设头像。
| 并发 worker | 时长 | 刷题写入比例 | 请求数 | 错误率 | 吞吐 | P95 | P99 | 结论 |
| ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | --- |
| 30 | 120s | 0% | 64,382 | 0.00% | 532.97 req/s | 140.64 ms | 193.69 ms | 通过只读上线门禁 |
| 50 | 60s | 10% | 40,065 | 0.00% | 658.11 req/s | 151.63 ms | 188.07 ms | 混合读写舒适 |
| 100 | 60s | 8% | 37,290 | 0.00% | 610.57 req/s | 303.93 ms | 376.47 ms | 接近舒适区上沿 |
| 150 | 60s | 6% | 33,952 | 0.00% | 555.08 req/s | 490.53 ms | 639.05 ms | 零错误但进入压力区 |
本轮 `npm run perf:summary` 校验结果:
- 30 worker 只读门禁通过,满足 `errors=0``errorRate<=0.001``p95<=300ms``p99<=800ms``duration>=120s`
- 50/100/150 worker 混合读写均为 0 错误100 worker 已接近 `P95=300ms` 舒适线150 worker 只作为压力上沿观察。
## 初步结论
- 本地 Docker 环境下50 worker 混合读写 P95 约 151.63ms100 worker 混合读写 P95 约 303.93ms100 worker 已接近当前本机舒适区上沿150 worker 仍然 0 错误,但 P95 约 490.53ms,已经是压力区。
- 按最新 658 req/s 的 50 worker 舒适吞吐粗略折算,如果未来前端真实埋点显示每名在线学生平均 0.05 到 0.2 req/s则理论请求吞吐约对应 3,290 到 13,160 名活跃在线学生;按 100 worker 上沿 610 req/s 估算约为 3,050 到 12,210 名;按 150 worker 压力区 555 req/s 估算约为 2,775 到 11,100 名。这只是吞吐换算,不是生产 SLA。
- 当前 Docker Desktop 给了 20 CPU 和约 62.7GB 内存,生产如果使用 4 核 16G 单机,首版容量承诺建议先按本地折算值的 30% 到 50% 保守规划,再以云端复测和真实前端埋点上调。
- 正式容量承诺必须在目标 4 核 16G 云服务器、生产 PostgreSQL 参数、对象存储/CDN、真实前端请求节奏和生产网络下复跑。
## 后续复测
上云后按 `docs/refactor/performance-benchmark-runbook.md` 复跑至少以下场景:
1. 只读 30/50/100 并发阶梯。
2. 混合读写 30/50/100 并发阶梯。
3. 结合 `pg_stat_statements`、慢 SQL、CPU、I/O、连接池和锁等待确认瓶颈。
4. 把代表性结果写入本地 `docs/refactor/production-launch-evidence.json`,再执行 `npm run launch:gate`