chore: harden production readiness gates

This commit is contained in:
Codex
2026-07-01 06:09:23 +08:00
parent f3f6028633
commit bb938cf6e2
13 changed files with 695 additions and 63 deletions

View File

@@ -45,7 +45,7 @@ Supabase Auth 可继续作为最终 JWT 用户体系目标;本地重构期先
## 短信 Provider
本地默认是 `AUTH_SMS_PROVIDER=mock`,仅开发环境返回 `debugCode`。生产环境如果仍为 mock会直接拒绝发送
本地默认是 `AUTH_SMS_PROVIDER=mock`,仅开发环境返回 `debugCode`。生产环境只允许 `aliyun/aliyun-sms``tencent/tencent-sms`;如果仍为 mock 或写成未知 providerAPI 启动和 `readiness:production` 都会直接失败
真实 provider
@@ -58,6 +58,7 @@ Supabase Auth 可继续作为最终 JWT 用户体系目标;本地重构期先
- 租户级密钥写 `app_private.tenant_secrets(secret_scope='sms')` 或生产 Vault。
- 前端只能看到 provider 是否启用、签名展示名、隐私协议链接等非敏感配置。
- provider endpoint 默认使用官方域名,生产环境只允许 HTTPS 官方域名;本地测试可使用 `localhost/127.0.0.1` fake server。
- `readiness:production:db` 会检查 active/testing 短信 provider 的 `signName/templateCode``smsSdkAppId/signName/templateId`,并阻断公开配置里的 secret-like 字段。
### 阿里云短信配置示例
@@ -196,6 +197,7 @@ body: { "code": "<qq oauth code>", "redirectUri": "https://h5.example.com/auth/q
- `endpoint``userInfoEndpoint``openIdEndpoint` 默认使用官方 HTTPS 域名;生产环境不允许本地 HTTP fake endpoint。
- `appSecret/clientSecret/AppKey` 必须存入 `app_private.tenant_secrets(secret_scope='oauth')`,不能进入 `configPublic`
- QQ 的 `redirectUri` 必须与 QQ 互联后台登记的一致;多租户自定义域名上线前需要逐个配置或设计统一授权中转域名。
- `readiness:production:db` 会阻断 OAuth endpoint/redirectUri 为 HTTP、localhost 或非官方 provider endpoint也会阻断 active/testing provider 缺少对应私密 `tenant_secrets`
## 手机号绑定/换绑
@@ -282,6 +284,7 @@ body: { "code": "<qq oauth code>", "redirectUri": "https://h5.example.com/auth/q
- 订单已支付时重复通知只返回幂等成功,不重复开通权益。
- 支付成功事务内更新 `orders``payments``payment_events``entitlements`
- 支付密钥只允许放在 `app_private.tenant_secrets` 或生产 KMS/Vault。
- `readiness:production:db` 会阻断微信支付缺 `appId/merchantId/merchantSerialNo/notifyUrl`、支付宝缺 `appId/notifyUrl`、notifyUrl/returnUrl/退款回调为 HTTP 或 localhost、provider endpoint 非官方域名、公开配置混入 `privateKey/apiV3Key/secret/token` 等密钥字段。
### 资金对账

View File

@@ -1,6 +1,6 @@
# 后端当前能力盘点
更新时间2026-06-30
更新时间2026-07-01
当前后端已经完成商用 SaaS 题库系统的主干骨架PostgreSQL 多租户 schema、Node.js 业务 API、PocketBase 数据导入工具、本地 seed、API 集成测试和对象存储签名 provider。
@@ -18,6 +18,7 @@
| RLS/租户隔离 | 可联调 | 表层普遍有 `tenant_id` 和 RLS 策略API 已支持 `tk_` 迁移 session 与 Supabase Auth JWT 双入口,并覆盖跨租户/伪造身份集成测试;生产前继续补真实云端 JWT/RLS 回归 |
| API 分层 | 可联调 | `apps/api/src/core` + `apps/api/src/features/*` |
| Docker API | 可联调 | `docker-compose.api.yml``apps/api/Dockerfile` 可用 |
| 生产配置门禁 | 可联调 | `readiness:production`/`:db` 和 API/worker 启动 fail-fast 会阻断弱密钥、mock/未知短信 provider、legacy 身份头、local_dev/未知存储、非 HTTPS 存储公开 URL、非官方阿里云 OSS endpoint、阿里云 OSS 内网直签、未接外部资源扫描、provider 公开配置混入密钥、OAuth/支付回调非 HTTPS 或缺必填字段 |
| 测试 | 可联调 | `npm run check:refactor` 覆盖 TS 检查、导入校验、生产 readiness 脚本测试、seed、API 集成测试;排行榜已覆盖默认关闭、四类指标、班级范围和跨租户拒绝 |
| 根 workspace | 可联调 | 根目录已清理为新技术栈 monorepo 编排层 |
@@ -193,6 +194,7 @@
```bash
npx supabase db reset
npm run audit:runtime
npm run security:repo
npm run check:refactor
npm run check:taro
npm run build:taro:h5:student
@@ -212,9 +214,13 @@ npm run test:worker:assets
npm run test:worker:exports
npm run test:worker:public-banks
npm run test:worker:student-supervision
npm run smoke:launch-persona
npm run perf:api:local
git diff --check
```
当前产品边界:学生头像只支持男女预设,不做上传、裁剪或第三方头像同步;排行榜后端具备可选能力,但默认关闭,学生端默认不请求,只有租户显式购买/开启活动并完成专项压测后再补日/周榜预聚合和防刷。
`check:refactor` 包含:
- API TypeScript 检查

View File

@@ -23,8 +23,8 @@
1. 真实云端 Auth/JWKS、RLS 和生产配置验收:在预生产/生产执行 `readiness:production``readiness:production:db``smoke:auth:remote``test:rls` 并留档,生产关闭 `x-user-id` 和平台本地 key 兼容入口。
2. 真实旧数据人工复核:正式切换前处理 7 个已支付缺用户订单、22 个缺所属手册章节,并对题目、权益、订单、错题、资料和视频做人工抽样。
3. 真实 provider 联调:阿里云/腾讯云短信、微信小程序登录、微信网页登录、QQ 登录、微信支付、支付宝、支付/退款回调域名、官方账单格式抽样。
4. 对象存储生产安全:配置真实 OSS/COS/Supabase Storage bucket、外部 AV/内容安全扫描、CDN 防盗链、转码/CDN 级水印、生命周期策略和恢复演练。
3. 真实 provider 联调:阿里云/腾讯云短信、微信小程序登录、微信网页登录、QQ 登录、微信支付、支付宝、支付/退款回调域名、官方账单格式抽样。当前生产 readiness 已会阻断 mock/未知短信 provider、OAuth/支付回调非 HTTPS、支付缺 `notifyUrl`、公开配置混入密钥和 active provider 缺 `tenant_secrets`
4. 对象存储生产安全:配置真实 OSS/COS/Supabase Storage bucket、外部 AV/内容安全扫描、CDN 防盗链、转码/CDN 级水印、生命周期策略和恢复演练。API/worker 已会拒绝 local_dev、未知存储 provider、非 HTTPS 公开 URL 和阿里云 OSS 内网直签。
5. 生产容量复测:目标云服务器按 4 核 16G 调参文档设置 PostgreSQL再按 30/50/100 只读和混合读写矩阵复跑,生成 `production-launch-evidence.json` 并通过 `npm run launch:gate`
6. 备份、日志、告警、回滚和安全扫描完成数据库快照、恢复演练、日志告警、Codex Security 真实扫描和上线审批证据。
@@ -50,14 +50,14 @@
本轮使用 `npm run perf:api:docker-4c16g`API 容器限制为 2 CPU/4G、`DB_POOL_MAX=10`、关闭 legacy `x-user-id` 和平台本地 key压测鉴权使用 `PERF_AUTH_MODE=app_session` 的 Bearer session。数据库仍为本机 Docker Desktop Supabase/PostgreSQL未限制为 4 核 16G因此结果更接近“受限 API 容器 + 本机数据库”的预生产观察,不是最终云服务器 SLA。
压测暴露一个真实并发缺陷50 worker 混合读写中,交卷触发自动勋章发放时撞到 `user_badges_tenant_id_legacy_id_key`,产生 1 个 500。已修复为自动勋章只使用 `(tenant_id, user_id, badge_id)` 做业务幂等,不再写入自动生成 `legacy_id`;并新增 `scripts/auto-badge-concurrency-test.js`20 个并发触发同一学生同一勋章时只生成 1 条 `user_badges`
历史受限容器压测暴露一个真实并发缺陷50 worker 混合读写中,交卷触发自动勋章发放时撞到 `user_badges_tenant_id_legacy_id_key`,产生 1 个 500。已修复为自动勋章只使用 `(tenant_id, user_id, badge_id)` 做业务幂等,不再写入自动生成 `legacy_id`;并新增 `scripts/auto-badge-concurrency-test.js`20 个并发触发同一学生同一勋章时只生成 1 条 `user_badges`
| 场景 | 并发 worker | 时长 | 刷题写入比例 | 请求数 | 错误率 | 吞吐 | P95 | P99 | 结论 |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | --- |
| 只读上线门禁 | 30 | 120s | 0% | 42,982 | 0.00% | 357.28 req/s | 192.25 ms | 287.93 ms | 通过 |
| 混合读写 | 50 | 60s | 10% | 26,086 | 0.00% | 431.78 req/s | 207.10 ms | 283.57 ms | 舒适 |
| 混合读写 | 100 | 60s | 8% | 25,242 | 0.00% | 417.03 req/s | 383.30 ms | 464.22 ms | 接近舒适区上沿 |
| 混合读写 | 150 | 60s | 6% | 24,201 | 0.00% | 398.22 req/s | 567.89 ms | 706.09 ms | 压力区 |
| 只读上线门禁 | 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 | 压力区 |
混合读写包含真实刷题闭环:创建练习 session、拉取 session detail、提交答案、交卷、读取报告。
@@ -69,10 +69,10 @@
按目前常见页面节奏先用 `0.05 到 0.2 req/s/人` 粗略折算:
- 50 worker 舒适场景 432 req/s约等于 2,160 到 8,640 名活跃在线学生的请求吞吐。
- 100 worker 上沿场景 417 req/s约等于 2,085 到 8,340 名活跃在线学生的请求吞吐。
- 150 worker 压力场景 398 req/s约等于 1,990 到 7,960 名活跃在线学生的请求吞吐。
- 50 worker 舒适场景 416.54 req/s约等于 2,080 到 8,330 名活跃在线学生的请求吞吐。
- 100 worker 上沿场景 394.18 req/s约等于 1,970 到 7,880 名活跃在线学生的请求吞吐。
- 150 worker 压力场景 370.53 req/s约等于 1,850 到 7,410 名活跃在线学生的请求吞吐。
当前本地结论:在受限 API 容器下,后端真实刷题读写链路的舒适观察区间约为 417 到 432 req/s折算约 2,100 到 8,600 名活跃在线学生150 worker 仍 0 错误但 P95 已接近 600ms视为压力区不建议作为生产承诺。同日本地 API 进程 30 worker/30 秒/10% 写入观察到 15,864 请求、0 错误、513.56 req/s、P95 113.97ms受限 API 容器会明显压低上沿,因此上线承诺仍以云端受限资源复测为准。
当前本地结论:在受限 API 容器下,后端真实刷题读写链路的舒适观察区间约为 416 req/s折算约 2,080 到 8,330 名活跃在线学生;100 worker 仍可用但 P95 已超过 400ms150 worker 仍 0 错误但 P95 已超过 600ms视为压力区不建议作为生产承诺。受限 API 容器会明显压低上沿,因此上线承诺仍以云端受限资源复测为准。
正式对外容量必须等 4 核 16G 云服务器部署后复跑。保守规划时,生产首版建议先按本地折算值的 30% 到 50% 做容量承诺,约 630 到 4,300 名活跃在线学生等云端压测、CDN、对象存储和真实前端埋点完成后再上调。
正式对外容量必须等 4 核 16G 云服务器部署后复跑。保守规划时,生产首版建议先按本地折算值的 30% 到 50% 做容量承诺,约 620 到 4,160 名活跃在线学生等云端压测、CDN、对象存储和真实前端埋点完成后再上调。

View File

@@ -59,6 +59,7 @@
- 已覆盖学生、租户管理员、平台管理员、错租户、坏签名、禁用 legacy header 的 API 集成测试。
- 已补自定义角色模板、菜单/模块/字段级配置 API、班级/学生范围权限;已新增 `npm run test:rls` 本地动态 RLS 深测,覆盖主租户、合作商租户、无租户 claim、平台管理员旁路和跨租户写入拒绝已新增 `npm run smoke:auth:remote` 用真实 Supabase access token 验收云端 Auth/JWKS 映射;继续在预生产/生产执行并留档。
- 前端联调时禁止继续使用 `x-user-id``x-tenant-id` 只作为租户上下文,不能作为身份依据。
- 生产 `.env` 必须通过 `readiness:production`:短信 provider 只允许阿里云/腾讯云,禁止 mock/未知值,禁止弱密钥、`CORS=*` 和 legacy 身份头。生产数据库还必须通过 `readiness:production:db`,校验租户短信/OAuth/支付 provider 的公开配置、HTTPS 回调、私密 `tenant_secrets` 和 RLS。
2. 对象存储
- 已接阿里云 OSS、腾讯云 COS、Supabase Storage 的上传/下载签名 provider。
@@ -71,7 +72,7 @@
- 已补租户后台媒体运营报表,支持资料/视频访问汇总、Top 资源/视频和 traceId 回查;大租户后续再把实时查询替换为日/周预聚合。
- 已收紧锁定资源 CDN 边界:`members/svip/private` 外链默认拒绝,必须显式 provider-managed 才允许;视频绑定资源也复用该策略。
- 已补外部 HTTP 杀毒/内容安全 scanner 接入层、失败关闭、生产 readiness 阻断和动态水印 traceId 审计;继续联调真实扫描服务、转码/CDN 级水印、CDN 刷新和对象生命周期策略。
- 已补 API/worker 生产启动 fail-fast生产环境会拒绝 `local_dev` 存储、空 bucket、关闭租户前缀worker 会拒绝未接入外部 HTTP scanner 或 fail-open。
- 已补 API/worker 生产启动 fail-fast生产环境会拒绝 `local_dev` 存储、未知存储 provider、空 bucket、关闭租户前缀、非 HTTPS `STORAGE_PUBLIC_BASE_URL`、阿里云 OSS 内网直签worker 会拒绝未接入外部 HTTP scanner 或 fail-open。
- 已补 `docs/refactor/object-storage-production-runbook.md`,真实云厂商联调必须按 runbook 抽样验收。
- `content_assets` 继续作为资源台账,不允许前端绕过台账直接访问私有资源。
@@ -94,7 +95,7 @@
- 已补 `npm run launch:gate` 生产上线证据门禁和 `docs/refactor/production-launch-evidence.template.json` 模板;最终切换前必须把 readiness、远程 Auth、RLS、PostgreSQL 4c16g 严格调参证据、生产 dry-run、导入校验、`pb:import:sample` 业务抽样、真实数据 API 只读压测、真实数据混合读写压测、API/worker/Taro、运行时审计、`security:repo`、真实 `@codex-security`、备份/回滚/真实抽样/生产 provider 等证据填入本地 `production-launch-evidence.json` 并通过门禁。当前 Codex 环境未暴露可调用的 `@codex-security` 扫描工具时,该项只能标为待补,不能伪造完成。
- 确认数据库迁移流程、备份恢复、日志、告警。
- 准备 API 容器部署和 Supabase 云端/自托管连接方案。
- 已补 `npm run perf:api:local``npm run perf:summary``npm run perf:postgres:evidence``npm run perf:postgres:sql``npm run smoke:launch-persona``npm run smoke:taro:h5``npm run smoke:taro:h5:interaction``node scripts/taro-api-contract-test.js``node scripts/taro-persona-contract-test.js``docs/refactor/performance-benchmark-runbook.md`可在本地或云端对真实迁移数据做只读门禁、混合读写容量观察、PostgreSQL 4c16g profile 调参证据、三类后端角色旅程烟测、三类 Taro 前端角色旅程契约、H5 发布目录启动烟测、真实浏览器关键点击烟测和前端 API 契约检查。2026-07-01 05:05 受限 API 容器真实迁移库复核中30 worker/120s 只读为 42,982 请求、0 错误、357.28 req/s、P95 192.25ms、P99 287.93ms50 worker/60s/10% 写入为 26,086 请求、0 错误、431.78 req/s、P95 207.10ms、P99 283.57ms100 worker/60s/8% 写入为 25,242 请求、0 错误、417.03 req/s、P95 383.30ms、P99 464.22ms150 worker/60s/6% 写入为 24,201 请求、0 错误、398.22 req/s、P95 567.89ms、P99 706.09ms。受限容器系列压测曾抓到自动勋章并发发放唯一键冲突已修复并新增 `scripts/auto-badge-concurrency-test.js`。当前 Docker Desktop 给了 20 CPU/约 62.7GB 内存,但 API 容器限制为 2 CPU/4G舒适观察区暂按 50 到 100 个无停顿 worker 估算150 worker 已是压力区;按单学生 0.05 到 0.2 req/s 粗略折算约为 2,100 到 8,600 名活跃在线学生的本机吞吐观察区间,正式容量仍以上云 4 核 16G 复测为准。
- 已补 `npm run perf:api:local``npm run perf:summary``npm run perf:postgres:evidence``npm run perf:postgres:sql``npm run smoke:launch-persona``npm run smoke:taro:h5``npm run smoke:taro:h5:interaction``node scripts/taro-api-contract-test.js``node scripts/taro-persona-contract-test.js``docs/refactor/performance-benchmark-runbook.md`可在本地或云端对真实迁移数据做只读门禁、混合读写容量观察、PostgreSQL 4c16g profile 调参证据、三类后端角色旅程烟测、三类 Taro 前端角色旅程契约、H5 发布目录启动烟测、真实浏览器关键点击烟测和前端 API 契约检查。2026-07-01 05:57 受限 API 容器真实迁移库复核中30 worker/120s 只读为 42,089 请求、0 错误、349.70 req/s、P95 202.20ms、P99 295.16ms50 worker/60s/10% 写入为 25,157 请求、0 错误、416.54 req/s、P95 215.00ms、P99 292.56ms100 worker/60s/8% 写入为 23,873 请求、0 错误、394.18 req/s、P95 414.67ms、P99 495.91ms150 worker/60s/6% 写入为 22,523 请求、0 错误、370.53 req/s、P95 621.55ms、P99 750.70ms。受限容器系列压测曾抓到自动勋章并发发放唯一键冲突已修复并新增 `scripts/auto-badge-concurrency-test.js`。当前 Docker Desktop 给了 20 CPU/约 62.7GB 内存,但 API 容器限制为 2 CPU/4G舒适观察区暂按 50 个无停顿 worker 估算,100 worker 可用但延迟偏高,150 worker 已是压力区;按单学生 0.05 到 0.2 req/s 粗略折算约为 2,080 到 8,330 名活跃在线学生的本机吞吐观察区间,正式容量仍以上云 4 核 16G 复测为准。
- 当前本地 PostgreSQL evidence 仍提示 `jit=on``statement_timeout=0``idle_in_transaction_session_timeout=0``lock_timeout=0`;上云后必须按 `docs/refactor/postgresql-4c16g-tuning.md` 调整参数,执行 `PG_TUNING_PROFILE=shared-host npm run perf:postgres:evidence -- --strict --json` 并通过后,再按 6/30/50/100 阶梯并发复跑容量报告并归档到本地上线证据。
- 本轮剩余功能和容量复核已经整理到 `docs/refactor/backend-open-items-and-capacity-20260701.md`。后续不要再把学生头像上传或默认排行榜当作待办;头像只保留男女预设,排行榜仅作为租户显式开启后的活动能力。
@@ -145,7 +146,7 @@
8. 订单和营销体验
- 已完成订单详情、订单状态轮询、激活码预检查、优惠券前台领取、下单抵扣计算、优惠券复杂规则、核销明细/报表和内部退款状态机。
- 已完成支付/退款补偿 worker、官方账单下载 worker、资金对账导入比对、差错工单、异常订单运营台和人工调整凭证复核Taro 财务运营台第一版已接入;本地继续验证回调后业务链路、幂等、审计、权益开通/撤销和密钥不泄露,真实生产账号、回调域名和账单格式抽样验收上云后补齐;继续补学生端售后入口深化、营销活动 UI 和活动效果看板。
- 已完成支付/退款补偿 worker、官方账单下载 worker、资金对账导入比对、差错工单、异常订单运营台和人工调整凭证复核Taro 财务运营台第一版已接入;`readiness:production:db` 已会阻断支付公开配置缺 `notifyUrl`、回调非 HTTPS、公开配置混入密钥和 active payment 缺私密密钥。本地继续验证回调后业务链路、幂等、审计、权益开通/撤销和密钥不泄露,真实生产账号、回调域名和账单格式抽样验收上云后补齐;继续补学生端售后入口深化、营销活动 UI 和活动效果看板。
9. 积分和反馈增强
- 已完成每日签到、积分流水、反馈提交、租户后台处理、奖励积分幂等。
@@ -199,7 +200,7 @@
4. 运维
- 后台操作审计报表。
- 定时备份、恢复演练。
- 性能压测、慢 SQL、索引审查当前已有 API 压测脚本、真实刷题读写闭环和 4 核 16G runbook,本地真实迁移数据已完成 30/50/100/150 并发阶梯压测,云服务器部署后还要按同一矩阵复跑并输出正式容量报告。
- 性能压测、慢 SQL、索引审查当前已有 API 压测脚本、真实刷题读写闭环和 4 核 16G runbook。最新 Docker API 受限资源复核为 30 并发只读 0 错误、349.7 req/s、P95 202ms50 并发混合读写 0 错误、416.5 req/s、P95 215ms100 并发混合读写 0 错误、394.2 req/s、P95 415ms150 并发混合读写 0 错误、370.5 req/s、P95 622ms。云服务器部署后还要按同一矩阵复跑并输出正式容量报告。
## Taro 前端开发 TODO

View File

@@ -17,7 +17,7 @@
- `NODE_ENV=production` 下 API 和 worker 都不能使用 `STORAGE_DEFAULT_PROVIDER=local_dev`
- `STORAGE_DEFAULT_BUCKET` 必须配置。
- `STORAGE_REQUIRE_TENANT_PREFIX=true` 必须保持开启。
- 阿里云 OSS 必须配置 `ALIYUN_OSS_REGION` `ALIYUN_OSS_ENDPOINT`,以及 AccessKey。
- 阿里云 OSS 必须配置 `ALIYUN_OSS_REGION`、官方 HTTPS `aliyuncs.com` `ALIYUN_OSS_ENDPOINT`,以及 AccessKey;生产禁止 `ALIYUN_OSS_INTERNAL=true` 用于面向用户的签名 URL
- 腾讯云 COS 必须配置 `TENCENT_COS_REGION``TENCENT_COS_APP_ID``TENCENT_COS_SECRET_ID``TENCENT_COS_SECRET_KEY`
- Supabase Storage 必须配置 `SUPABASE_STORAGE_URL``SUPABASE_STORAGE_SERVICE_KEY`
- `WORKER_ASSET_SECURITY_SCANNER` 生产必须包含 `http`,例如 `metadata_rules,http`
@@ -213,4 +213,3 @@ npm --workspace @tiku-saas/worker run exports:once
- API/worker 在 `NODE_ENV=production` 下无法用 `local_dev` 启动。
- 真实云存储上传、确认、扫描、发布、预览、下载、导出全链路通过。
- 云侧 CORS、防盗链、生命周期、备份/版本控制、访问日志有截图或变更记录。

View File

@@ -115,11 +115,30 @@
按 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 名活跃在线学生请求吞吐,再以上云复测和真实前端埋点修正。
## 初步结论
- 本地 Docker 环境下50 worker 混合读写 P95 约 174.26ms100 worker 混合读写 P95 约 326.21ms100 worker 已接近当前本机舒适区上沿150 worker 仍然 0 错误,但 P95 约 490.38ms已经压力区。
- 按最新 584 req/s 的 50 worker 舒适吞吐粗略折算,如果未来前端真实埋点显示每名在线学生平均 0.05 到 0.2 req/s则理论请求吞吐约对应 2,920 到 11,680 名活跃在线学生;按 100 worker 上沿 554 req/s 估算约为 2,770 到 11,080 名;按 150 worker 压力区 529 req/s 估算约为 2,645 到 10,580 名。这只是吞吐换算,不是生产 SLA。
- 当前 Docker Desktop 给了 20 CPU 和约 62.7GB 内存,生产如果使用 4 核 16G 单机,首版容量承诺建议先按本地折算值的 30% 到 50% 保守规划,再以云端复测真实前端埋点上调。
- 本地高资源 Docker Desktop 历史结果显示代码和索引在 50/100 worker 下有较高吞吐;但最新受限 API 容器复核更接近保守上线口径50 worker 混合读写 P95 约 215ms100 worker P95 约 415ms150 worker P95 约 622ms 已经进入压力区。
- 按最新 416.54 req/s 的 50 worker 舒适吞吐粗略折算,如果未来前端真实埋点显示每名在线学生平均 0.05 到 0.2 req/s则理论请求吞吐约对应 2,080 到 8,330 名活跃在线学生;按 100 worker 上沿 394.18 req/s 估算约为 1,970 到 7,880 名;按 150 worker 压力区 370.53 req/s 估算约为 1,850 到 7,410 名。这只是吞吐换算,不是生产 SLA。
- 生产如果使用 4 核 16G 单机,首版容量承诺建议先按最新本地受限资源折算值的 30% 到 50% 保守规划,即约 620 到 4,160 名活跃在线学生请求吞吐,再以云端复测真实前端埋点、CDN/对象存储和生产 PostgreSQL 调参后结果上调。
- 正式容量承诺必须在目标 4 核 16G 云服务器、生产 PostgreSQL 参数、对象存储/CDN、真实前端请求节奏和生产网络下复跑。
## 后续复测

View File

@@ -82,6 +82,8 @@ npm run security:repo
npm run check:api
npm run check:worker
npm run check:taro
npm run readiness:production
npm run readiness:production:db
npm run smoke:taro:h5
npm run smoke:taro:h5:interaction
node scripts/taro-h5-release-guardrails-test.js --require-dist
@@ -100,12 +102,15 @@ node scripts/taro-h5-release-guardrails-test.js --require-dist --require-runtime
`security:repo` 是仓库自带的静态安全扫描,会拦截密钥形态、前端旧鉴权头、真实 runtime-config 和生产证据误入 Git。它不能替代真实 `@codex-security`;如插件在当前 Codex 环境暴露扫描工具,再补插件扫描结果。若工具不可用,不能把该项标记为已完成,只能在上线证据里标记为待补。
`readiness:production``readiness:production:db` 是生产阻断门禁:会拒绝 mock/未知短信 provider、弱密钥、`CORS=*`、旧身份头、local_dev 存储、非 HTTPS 对象存储公开 URL、阿里云 OSS 内网直签、未接外部资源扫描、localhost webhook以及租户短信/OAuth/支付公开配置缺字段、OAuth redirectUri/支付 notifyUrl 非 HTTPS、公开配置混入密钥、active provider 缺私密 `tenant_secrets` 等问题。
生产 API 推荐:
```text
ALLOW_LEGACY_AUTH_HEADERS=false
ALLOW_PLATFORM_ADMIN_KEY=false
CORS_ORIGIN=https://student.example.com,https://tenant-admin.example.com,https://platform-admin.example.com
AUTH_SMS_PROVIDER=aliyun 或 tencent
```
生产 worker 推荐:
@@ -115,6 +120,7 @@ WORKER_ASSET_SECURITY_SCANNER=metadata_rules,http
WORKER_ASSET_SECURITY_SCAN_FAIL_OPEN=false
STORAGE_DEFAULT_PROVIDER=aliyun_oss 或 tencent_cos 或 supabase_storage
STORAGE_REQUIRE_TENANT_PREFIX=true
ALIYUN_OSS_INTERNAL=false
```
## 性能与数据库