20 KiB
真实迁移数据 API 压测摘要
更新时间:2026-07-01
这份文件只记录脱敏后的聚合指标,便于 README、上线门禁和后续 AI 开发继续引用。原始 JSON/Markdown 报告位于已忽略的 docs/refactor/performance-reports/,不要提交到 Git。
测试口径
- 环境:本地 Docker Desktop + 本地 Supabase/PostgreSQL + 本地 API 进程。
- 数据:PocketBase 真实导出数据导入新 PostgreSQL 后压测。
- 数据规模:当前真实迁移库已包含前期压测写入记录,约 19 个租户、74,131 道题、1,631 个题目合集、3,120 个练习蓝图、3,519 个单词、2,692 条知识手册、3,722 个用户、72,710 个练习 session、302,585 条答题记录、38,207 条错题、1,501 个内容资源和 472 条权益。
- 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 02:48 真实数据容量复核
本轮按用户最新要求重新确认本地 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 只作为压力上沿观察。
2026-07-01 03:12 真实数据容量复核
本轮在同一套本地 Docker/Supabase 真实迁移库上继续复跑,并先执行 npm run smoke:launch-persona 确认三类角色旅程通过。普通学生旅程覆盖 SVIP 后刷题、收藏和错题复习入口;租户管理员旅程覆盖 dashboard、主题、学生和销售转化入口;平台管理员旅程覆盖租户、套餐和审计入口;同时验证学生访问后台、租户管理员跨租户访问和学生访问平台后台均被拒绝。
| 并发 worker | 时长 | 刷题写入比例 | 请求数 | 错误率 | 吞吐 | P95 | P99 | 结论 |
|---|---|---|---|---|---|---|---|---|
| 30 | 120s | 0% | 60,326 | 0.00% | 499.27 req/s | 151.29 ms | 214.61 ms | 通过只读上线门禁 |
| 50 | 60s | 10% | 35,608 | 0.00% | 584.18 req/s | 174.26 ms | 224.04 ms | 混合读写舒适 |
| 100 | 60s | 8% | 33,843 | 0.00% | 554.42 req/s | 326.21 ms | 422.33 ms | 接近舒适区上沿 |
| 150 | 60s | 6% | 32,364 | 0.00% | 528.81 req/s | 490.38 ms | 662.42 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 已接近舒适区上沿,150 worker 只作为压力观察,不作为生产承诺。
按 0.05 到 0.2 req/s/人的页面节奏粗略折算,50 worker 舒适吞吐约对应 2,920 到 11,680 名活跃在线学生请求吞吐,100 worker 上沿约对应 2,770 到 11,080 名,150 worker 压力区约对应 2,645 到 10,580 名。该数字仍是本地 Docker 观察值,正式承诺必须在目标 4 核 16G 云服务器和真实前端埋点下复跑。
2026-07-01 05:57 Docker API 受限资源复核
本轮在完成生产 provider readiness 加固、npm run smoke:launch-persona、npm run smoke:taro:h5:interaction 和 npm run perf:postgres:evidence 后复跑。压测入口为 npm run perf:api:docker-4c16g,API 容器按脚本默认限制为 2 CPU/4G,使用 PERF_AUTH_MODE=app_session,排行榜仍未纳入默认负载。
| 并发 worker | 时长 | 刷题写入比例 | 请求数 | 错误率 | 吞吐 | P95 | P99 | 结论 |
|---|---|---|---|---|---|---|---|---|
| 30 | 120s | 0% | 42,089 | 0.00% | 349.70 req/s | 202.20 ms | 295.16 ms | 通过只读上线门禁 |
| 50 | 60s | 10% | 25,157 | 0.00% | 416.54 req/s | 215.00 ms | 292.56 ms | 混合读写舒适 |
| 100 | 60s | 8% | 23,873 | 0.00% | 394.18 req/s | 414.67 ms | 495.91 ms | 可用但延迟偏高 |
| 150 | 60s | 6% | 22,523 | 0.00% | 370.53 req/s | 621.55 ms | 750.70 ms | 零错误但进入压力区 |
本轮 npm run perf:summary 校验结果:
- 30 worker 只读门禁通过,满足
errors=0、errorRate<=0.001、p95<=300ms、p99<=800ms、duration>=120s。 - 50 worker 混合读写满足
P95<=500ms/P99<=1200ms,是当前受限 API 容器下更保守的舒适区。 - 100 worker 混合读写仍 0 错误,P95 约 415ms,适合作为上沿观察;150 worker P95 约 622ms,只作为压力区观察,不作为生产承诺。
按 0.05 到 0.2 req/s/人的页面节奏粗略折算,50 worker 舒适吞吐约对应 2,080 到 8,330 名活跃在线学生请求吞吐;100 worker 上沿约对应 1,970 到 7,880 名;150 worker 压力区约对应 1,850 到 7,410 名。生产 4 核 16G 首版容量建议先按这组本地受限资源折算值的 30% 到 50% 保守规划,即约 620 到 4,160 名活跃在线学生请求吞吐,再以上云复测和真实前端埋点修正。
2026-07-01 06:26 Docker API + DB 显式受限复核
本轮使用 BENCHMARK_LIMIT_DB_RESOURCES=true npm run perf:api:docker-4c16g,API 容器限制为 2 CPU/4G,Supabase PostgreSQL 容器限制为 2 CPU/8G,DB_POOL_MAX=10,压测鉴权继续使用 PERF_AUTH_MODE=app_session。这比 05:57 只限制 API 容器更接近本地 4C16G 资源压力,但 PostgreSQL 参数仍是本地默认值,并未按 docs/refactor/postgresql-4c16g-tuning.md 应用 shared-host profile。
| 场景 | 并发 worker | 时长 | 刷题写入比例 | 请求数 | 错误率 | 吞吐 | P95 | P99 | 门禁结论 |
|---|---|---|---|---|---|---|---|---|---|
| 只读上线门禁 | 30 | 120s | 0% | 8,029 | 0.00% | 66.50 req/s | 1188.62 ms | 1697.71 ms | 失败,超过 P95/P99 |
| 混合读写 | 50 | 60s | 10% | 7,088 | 0.00% | 115.82 req/s | 905.13 ms | 1211.98 ms | 失败,超过 P95/P99 |
| 混合读写 | 100 | 60s | 8% | 6,383 | 0.00% | 103.63 req/s | 1720.26 ms | 2101.02 ms | 压力区 |
| 混合读写 | 150 | 60s | 6% | 5,640 | 0.00% | 91.52 req/s | 2688.31 ms | 3284.99 ms | 压力区 |
结论:资源更严格后系统仍保持 0 错误,但延迟不满足上线门禁。该结果不能作为生产容量承诺,反而证明云端正式部署前必须先完成 PostgreSQL shared-host 调参、pg_stat_statements、慢 SQL 观察和 4C16G 云服务器复测。尤其是 learning.trend、learning.stats、learning.practice_flow.create/detail/answer 在受限 DB 下最容易抬高 P95,应在云端结合慢 SQL 和 EXPLAIN (ANALYZE, BUFFERS) 继续看是否需要预聚合、缓存或索引微调。
按 50 worker 混合读写 115.82 req/s 粗略折算,理论请求吞吐约对应 580 到 2,316 名活跃在线学生,但因为该轮未完成 PostgreSQL 调参且只在本地 Docker Desktop 上运行,只能作为“未调参受限资源下限观察”,不能作为首版生产规划值。首版生产规划仍以上云调参后复测为准。
2026-07-01 06:44 Docker API 受限资源复核
本轮在新增 scripts/product-scope-guardrails-test.js 并完成 npm run test:readiness、npm run security:repo、npm run audit:runtime、API/worker/Taro 类型检查、npm run smoke:taro:h5、npm run smoke:taro:h5:interaction 和 npm run smoke:launch-persona 后复跑。压测入口仍为 npm run perf:api:docker-4c16g,API 容器限制为 2 CPU/4G,DB_POOL_MAX=10,压测鉴权使用 PERF_AUTH_MODE=app_session。数据库未额外限制,仍可使用 Docker Desktop 全局资源;排行榜未纳入默认负载。
| 场景 | 并发 worker | 时长 | 刷题写入比例 | 请求数 | 错误率 | 吞吐 | P95 | P99 | 门禁结论 |
|---|---|---|---|---|---|---|---|---|---|
| 只读上线门禁 | 30 | 120s | 0% | 38,724 | 0.00% | 321.92 req/s | 225.17 ms | 338.35 ms | 通过 |
| 混合读写 | 50 | 60s | 10% | 23,810 | 0.00% | 394.19 req/s | 235.96 ms | 320.19 ms | 通过 |
| 混合读写 | 100 | 60s | 8% | 23,384 | 0.00% | 386.14 req/s | 417.12 ms | 498.89 ms | 上沿观察 |
| 混合读写 | 150 | 60s | 6% | 22,314 | 0.00% | 366.79 req/s | 613.15 ms | 744.50 ms | 压力区 |
本轮 npm run perf:summary 校验结果:
- 30 worker 只读门禁通过,满足
errors=0、errorRate<=0.001、p95<=300ms、p99<=800ms、duration>=120s。 - 50 worker 混合读写满足
P95<=500ms/P99<=1200ms,仍是当前受限 API 容器下的舒适观察区。 - 100/150 worker 均 0 错误,但 P95 已进入上沿/压力区,不作为生产承诺。
按 0.05 到 0.2 req/s/人的页面节奏粗略折算,50 worker 舒适吞吐约对应 1,970 到 7,880 名活跃在线学生请求吞吐;100 worker 上沿约对应 1,930 到 7,720 名;150 worker 压力区约对应 1,830 到 7,330 名。该数字仍是本地 API 受限、DB 未受限观察值,正式容量必须在目标云服务器和真实前端埋点下复跑。
2026-07-01 06:53 Docker API + DB 显式受限复核
本轮使用 BENCHMARK_LIMIT_DB_RESOURCES=true npm run perf:api:docker-4c16g,API 容器限制为 2 CPU/4G,Supabase PostgreSQL 容器限制为 2 CPU/8G,DB_POOL_MAX=10。PostgreSQL 参数仍是本地默认值,并未应用 docs/refactor/postgresql-4c16g-tuning.md 的 shared-host profile。
| 场景 | 并发 worker | 时长 | 刷题写入比例 | 请求数 | 错误率 | 吞吐 | P95 | P99 | 门禁结论 |
|---|---|---|---|---|---|---|---|---|---|
| 只读上线门禁 | 30 | 120s | 0% | 8,397 | 0.00% | 69.48 req/s | 1183.29 ms | 1697.59 ms | 失败,超过 P95/P99 |
| 混合读写 | 50 | 60s | 10% | 6,640 | 0.00% | 109.61 req/s | 996.01 ms | 1303.45 ms | 失败,超过 P95/P99 |
| 混合读写 | 100 | 60s | 8% | 6,381 | 0.00% | 104.13 req/s | 1705.51 ms | 2098.41 ms | 压力区 |
| 混合读写 | 150 | 60s | 6% | 5,211 | 0.00% | 83.23 req/s | 3006.71 ms | 3699.64 ms | 压力区 |
结论:资源更严格后系统仍保持 0 错误,但延迟不满足上线门禁。按 50 worker 混合读写 109.61 req/s 粗略折算,理论请求吞吐约对应 548 到 2,192 名活跃在线学生;由于该轮未调 PostgreSQL 参数且只在本地 Docker Desktop 上运行,只能作为“未调参受限资源下限观察”,不能作为首版生产规划值。
2026-07-01 07:59 Docker API 受限资源复核
本轮在增强 scripts/taro-h5-interaction-smoke.js 后复跑。H5 真实交互烟测已覆盖学生端核心旅程、租户后台内容导入/公共题库/学生运营/营销 CRM 分佣/主题角色成员写操作,以及平台后台租户/账务/题库授权/员工写操作,结果为 32/32 通过。随后使用 npm run perf:api:docker-4c16g 在真实迁移库上复跑 30/50/100/150 阶梯;API 容器限制为 2 CPU/4G,数据库未额外限制,压测鉴权为 PERF_AUTH_MODE=app_session。排行榜仍未纳入默认负载,头像相关链路不参与压测,因为学生头像产品策略已固定为男女预设头像。
| 场景 | 并发 worker | 时长 | 刷题写入比例 | 请求数 | 错误率 | 吞吐 | P95 | P99 | 门禁结论 |
|---|---|---|---|---|---|---|---|---|---|
| 只读上线门禁 | 30 | 120s | 0% | 36,800 | 0.00% | 305.59 req/s | 241.46 ms | 351.17 ms | 通过 |
| 混合读写 | 50 | 60s | 10% | 24,120 | 0.00% | 398.79 req/s | 231.28 ms | 325.94 ms | 通过 |
| 混合读写 | 100 | 60s | 8% | 22,462 | 0.00% | 370.86 req/s | 445.26 ms | 532.32 ms | 上沿观察 |
| 混合读写 | 150 | 60s | 6% | 20,708 | 0.00% | 340.74 req/s | 689.67 ms | 833.08 ms | 压力区 |
本轮结论:
- 30 worker 只读门禁通过,满足
errors=0、errorRate<=0.001、p95<=300ms、p99<=800ms、duration>=120s。 - 50 worker 混合读写满足
P95<=500ms/P99<=1200ms,仍是当前受限 API 容器下的舒适观察区。 - 100 worker 混合读写 0 错误但 P95 已到 445.26ms,适合作为上沿观察;150 worker 0 错误但 P95 已到 689.67ms,只作为压力区观察。
按 0.05 到 0.2 req/s/人的页面节奏粗略折算,50 worker 舒适吞吐约对应 1,994 到 7,976 名活跃在线学生请求吞吐;100 worker 上沿约对应 1,854 到 7,417 名;150 worker 压力区约对应 1,704 到 6,815 名。该数字仍是本地 API 受限、DB 未受限观察值,正式容量必须在目标云服务器和真实前端埋点下复跑。
初步结论
- 本地高资源 Docker Desktop 历史结果显示代码和索引在 50/100 worker 下有较高吞吐;只限制 API 容器时,最新 50 worker 混合读写 P95 约 231ms,100 worker P95 约 445ms,150 worker P95 约 690ms;进一步把 DB 容器也限制为 2 CPU/8G 后,30 worker 只读和 50 worker 混合读写均未通过延迟门禁。
- 最新 DB 显式受限结果说明:不能仅凭本地 Docker API 受限跑分给生产承诺,生产 4C16G 必须先应用 PostgreSQL shared-host 调参并启用
pg_stat_statements,再跑正式只读/混合读写矩阵。 - 生产如果使用 4 核 16G 单机,首版容量承诺不要直接沿用本地 API-only 的人数估算;应先以云端调参后复测结果为准。没有云端复测前,可以把 07:59 结果看作“API 受限但 DB 未受限的乐观观察”,把 06:53 结果看作“DB 也受限但未调参的悲观观察”。
- 正式容量承诺必须在目标 4 核 16G 云服务器、生产 PostgreSQL 参数、对象存储/CDN、真实前端请求节奏和生产网络下复跑。
后续复测
上云后按 docs/refactor/performance-benchmark-runbook.md 复跑至少以下场景:
- 只读 30/50/100 并发阶梯。
- 混合读写 30/50/100 并发阶梯。
- 结合
pg_stat_statements、慢 SQL、CPU、I/O、连接池和锁等待确认瓶颈。 - 把代表性结果写入本地
docs/refactor/production-launch-evidence.json,再执行npm run launch:gate。