chore: gate production postgres tuning and taro handoff

This commit is contained in:
Codex
2026-07-01 04:27:19 +08:00
parent 6bdb2a175a
commit 69b4d3b62d
14 changed files with 702 additions and 44 deletions

View File

@@ -20,11 +20,13 @@
- Taro 启动、租户解析、请求封装、页面/API 映射、跨端注意事项。
7. `docs/refactor/taro-h5-deployment.md`
- H5 三域名部署、`runtime-config.json`、Nginx history fallback、缓存、CSP 和 CORS 边界。
8. `docs/refactor/multitenant-auth-security-contract.md`
8. `docs/refactor/taro-production-integration-checklist.md`
- 正式接 Supabase Auth、三套 H5、真实 provider、runtime-config 和上线门禁时逐项对照。
9. `docs/refactor/multitenant-auth-security-contract.md`
- 多租户、鉴权、权限、资源签名和生产安全红线。
9. `docs/refactor/content-import-contract.md`
10. `docs/refactor/content-import-contract.md`
- 后台内容导入、题目 JSON、单词、知识手册、分数线、视频的后端校验契约。
10. `docs/refactor/production-launch-evidence.template.json`
11. `docs/refactor/production-launch-evidence.template.json`
- 上线前证据文件模板;真实生产验收结果填入 `production-launch-evidence.json` 后运行 `npm run launch:gate`,该真实证据文件不入 Git。
## 当前可进入的前端工作

View File

@@ -91,11 +91,11 @@
- 生产 `.env` 模板和 `npm run readiness:production` / `npm run readiness:production:db` 已补,后续上云必须作为验收 gate。
- Auth/JWKS 上云后必须临时设置 `AUTH_SMOKE_*` 环境变量并运行 `npm run smoke:auth:remote`,真实 access token 不得写入仓库、前端配置或日志。
- 本地/预生产必须同时跑 `npm run test:rls`,它验证运行时 JWT claim 下的租户隔离,和 `readiness:production:db` 的静态 policy 检查互补。
- 已补 `npm run launch:gate` 生产上线证据门禁和 `docs/refactor/production-launch-evidence.template.json` 模板;最终切换前必须把 readiness、远程 Auth、RLS、生产 dry-run、导入校验、`pb:import:sample` 业务抽样、真实数据 API 读路径压测、API/worker/Taro、运行时审计、`@codex-security`、备份/回滚/真实抽样/生产 provider 等证据填入本地 `production-launch-evidence.json` 并通过门禁。当前 Codex 环境未暴露可调用的 `@codex-security` 扫描工具时,该项只能标为待补,不能伪造完成。
- 已补 `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、运行时审计、`@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 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 调参证据、三类后端角色旅程烟测、三类 Taro 前端角色旅程契约、H5 发布目录启动烟测、真实浏览器关键点击烟测和前端 API 契约检查。2026-07-01 03:58 受限 API 容器真实迁移库复核中30 worker/120s 只读为 44,038 请求、0 错误、366.27 req/s、P95 185.80ms、P99 254.08ms50 worker/60s/10% 写入为 25,327 请求、0 错误、419.62 req/s、P95 213.17ms、P99 270.94ms100 worker/60s/8% 写入为 25,378 请求、0 错误、417.77 req/s、P95 383.72ms、P99 461.22ms150 worker/60s/6% 写入为 23,444 请求、0 错误、384.39 req/s、P95 605.89ms、P99 743.19ms。压测先抓到自动勋章并发发放唯一键冲突,已修复并新增 `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,000 到 8,400 名活跃在线学生的本机吞吐观察区间,正式容量仍以上云 4 核 16G 复测为准。
- 当前本地 PostgreSQL evidence 仍提示 `jit=on``statement_timeout=0``idle_in_transaction_session_timeout=0``lock_timeout=0`;上云后必须按 `docs/refactor/postgresql-4c16g-tuning.md` 调整参数并复跑 evidence。4 核 16G 正式容量报告需上云后按 6/30/50/100 阶梯并发复跑并归档到本地上线证据。
- 已补 `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 03:58 受限 API 容器真实迁移库复核中30 worker/120s 只读为 44,038 请求、0 错误、366.27 req/s、P95 185.80ms、P99 254.08ms50 worker/60s/10% 写入为 25,327 请求、0 错误、419.62 req/s、P95 213.17ms、P99 270.94ms100 worker/60s/8% 写入为 25,378 请求、0 错误、417.77 req/s、P95 383.72ms、P99 461.22ms150 worker/60s/6% 写入为 23,444 请求、0 错误、384.39 req/s、P95 605.89ms、P99 743.19ms。压测先抓到自动勋章并发发放唯一键冲突,已修复并新增 `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,000 到 8,400 名活跃在线学生的本机吞吐观察区间,正式容量仍以上云 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`。后续不要再把学生头像上传或默认排行榜当作待办;头像只保留男女预设,排行榜仅作为租户显式开启后的活动能力。
### P1 商用功能完善

View File

@@ -37,6 +37,18 @@ npm run perf:postgres:evidence
该脚本会把关键 `pg_settings`、连接等待、缓存命中、大表大小和可选 `pg_stat_statements` Top SQL 输出到 `docs/refactor/launch-artifacts/`。调参前后各跑一次,配合 API 压测报告判断是否真正改善。
生产上线前必须用严格模式跑一次,并把摘要填入 `production-launch-evidence.json``postgres.tuning-evidence`
```bash
PG_TUNING_PROFILE=shared-host npm run perf:postgres:evidence -- --strict --json
```
严格模式要求 4c16g profile 范围内、无 `pending_restart``pg_stat_statements` 可用、`jit=off`,且 API 请求相关超时不为 0。需要生成 `ALTER SYSTEM` SQL 时使用:
```bash
npm run perf:postgres:sql -- --profile=shared-host
```
角色旅程烟测:
```bash
@@ -135,7 +147,7 @@ npm run perf:api:local
## 4 核 16G 阶梯压测建议
在云服务器上先按 `docs/refactor/postgresql-4c16g-tuning.md` 配置 shared-host 起步值,再跑以下矩阵。每轮之间间隔 2 到 5 分钟,观察 CPU、内存、磁盘 I/O、连接数和慢 SQL。
在云服务器上先按 `docs/refactor/postgresql-4c16g-tuning.md` 配置 shared-host 起步值,执行 `perf:postgres:evidence -- --strict` 通过,再跑以下矩阵。每轮之间间隔 2 到 5 分钟,观察 CPU、内存、磁盘 I/O、连接数和慢 SQL。
| 场景 | 并发 | 时长 | 写入 | 用途 |
| --- | ---: | ---: | --- | --- |

View File

@@ -1,6 +1,6 @@
# PostgreSQL 4 核 16G 生产调参基线
更新时间2026-06-30
更新时间2026-07-01
这份文档用于后续把 Supabase/PostgreSQL 自托管到 4 核 16G 云服务器时做生产起步配置。目标是先给题库 SaaS 一个安全、可回滚、可观测的基线,而不是追求一次性压满硬件。
@@ -12,7 +12,7 @@
- PostgreSQL 官方 WAL/Checkpointhttps://www.postgresql.org/docs/current/runtime-config-wal.html
- PostgreSQL 官方 Connectionshttps://www.postgresql.org/docs/current/runtime-config-connection.html
说明postgresqlco.nf 的页面可作为参数分类和调参入口参考;具体参数语义、重启要求和风险以 PostgreSQL 官方文档为准。
说明postgresqlco.nf 的页面可作为参数分类和调参入口参考;具体参数语义、重启要求和风险以 PostgreSQL 官方文档为准。当前 Codex 环境访问 `https://postgresqlco.nf/tuning-guide` 会返回 403因此落地值不直接抓取该站页面而是把它作为导航来源并以 PostgreSQL 官方文档和本项目真实压测结果共同校验。
## 适用前提
@@ -65,6 +65,26 @@ npm run perf:postgres:evidence
上云后建议顺序是:先采集一次默认值,应用本文件 shared-host 参数并重启需要重启的项,再采集一次,然后跑 API 阶梯压测。调参证据和压测报告一起进入本地 `production-launch-evidence.json`,不要提交真实证据文件。
生产上线门禁使用严格模式:
```bash
PG_TUNING_PROFILE=shared-host npm run perf:postgres:evidence -- --strict --json
```
严格模式会按 `scripts/lib/postgres-tuning-profile.js` 检查 4 核 16G profile
- `jit=off`
- `statement_timeout``idle_in_transaction_session_timeout``lock_timeout` 不得为 0。
- 所有 profile 参数必须在允许范围内。
- `pending_restart` 必须为 0。
- `pg_stat_statements` 必须可用。
如果 PostgreSQL 是独立数据库主机,可改用:
```bash
PG_TUNING_PROFILE=dedicated-db npm run perf:postgres:evidence -- --strict --json
```
## 应用连接池边界
4 核机器的关键不是把 `max_connections` 拉大,而是控制同时活跃 SQL 的数量。
@@ -107,7 +127,13 @@ where name in (
order by name;
```
同机部署推荐先执行:
同机部署推荐先生成 SQL 后人工复核再执行:
```bash
npm run perf:postgres:sql -- --profile=shared-host
```
等价的 shared-host 起步 SQL 如下:
```sql
alter system set max_connections = '80';

View File

@@ -29,6 +29,20 @@
"blocker": 0
}
},
{
"id": "postgres.tuning-evidence",
"status": "pass",
"command": "PG_TUNING_PROFILE=shared-host npm run perf:postgres:evidence -- --strict --json > docs/refactor/launch-artifacts/postgres-tuning-evidence.json",
"completedAt": "2026-06-30T10:08:00+08:00",
"artifact": "launch-artifacts/postgres-tuning-evidence.json",
"summary": {
"status": "pass",
"profile": "shared-host",
"failures": 0,
"pgStatStatementsAvailable": true,
"pendingRestart": 0
}
},
{
"id": "auth.remote-smoke",
"status": "pass",

View File

@@ -0,0 +1,108 @@
# Taro 生产接入检查清单
更新时间2026-07-01
这份清单给前端同事和后续 AI 使用。目标是让 `apps/taro` 的 H5 学生端、租户后台、平台后台按当前 Supabase/PostgreSQL 新后端上线,后续再扩展微信小程序。旧小程序前端文件在 `F:\project\参考\旧题库小程序前端文件`,只作为视觉、交互状态和微信平台能力参考,不继承旧 PocketBase 直连、旧 token、旧安全假设。
## 总原则
- Taro 负责 UI、路由、交互、公开 runtime config 和 Supabase Auth session。
- 复杂业务默认调用 `apps/api`,不要让页面直接写 Supabase 业务表。
- Supabase client 可用于 Auth session、可选 Realtime、公开只读 view/table 或经过 RLS/RPC 评审的低风险功能。
- 支付、短信、微信/QQ OAuth、订单、权益、激活码、优惠券、CRM、AI、导入、私有对象存储签名必须走 `apps/api`、Edge Function 或 worker。
- 页面代码不得覆盖 `Authorization``x-tenant-id`,不得发送 `x-user-id`
- 前端只做可见性优化,权限最终以后端/RLS/RPC 校验为准。
## 三套 H5 发布目录
建议三套 H5 分域部署,不共用 web root
| 门户 | 推荐域名 | 构建命令 | runtime-config |
| --- | --- | --- | --- |
| 学生端 | `https://www.example.com` 或租户自定义域名 | `npm run build:taro:h5:student` | `apps/taro/deploy/h5-student.runtime-config.example.json` |
| 租户后台 | `https://admin.example.com` | `npm run build:taro:h5:tenant` | `apps/taro/deploy/h5-tenant-admin.runtime-config.example.json` |
| 平台后台 | `https://console.example.com` | `npm run build:taro:h5:platform` | `apps/taro/deploy/h5-platform-admin.runtime-config.example.json` |
每个发布目录根部必须放置独立的 `runtime-config.json`,只允许公开字段:
```json
{
"portal": "student",
"apiBaseUrl": "https://api.example.com",
"supabaseUrl": "https://supabase.example.com",
"supabasePublishableKey": "sb_publishable_xxx",
"tenantCode": "optional-tenant-slug"
}
```
禁止出现在 `runtime-config.json`、Taro 环境变量、源码和构建产物中的内容:
- Supabase service role / secret key。
- 数据库连接串。
- 短信、OAuth、支付、对象存储、CRM、AI 的 secret/private key。
- 真实用户 token、测试 access token、平台本地管理 key。
## 生产接入步骤
1. 配好三套 H5 的 `runtime-config.json`,确认 `apiBaseUrl``supabaseUrl` 都是 HTTPS。
2. H5 登录优先使用 Supabase Auth access token迁移期 `tk_` session 只用于本地或内网联调。
3. 学生端先走完整路径:解析租户、登录、选择地区、进入题库、创建练习、答题、收藏、交卷、查看报告、错题/收藏复习、背单词、知识手册、资料预览/下载、视频授权、会员下单、订单轮询。
4. 租户后台先走完整路径:权限加载、学生运营、题库导入/任务/问题行、公共题库采纳、营销中心、财务运营、主题发布、角色模板和成员绑定。
5. 平台后台先走完整路径:平台权限加载、创建租户、租户详情、账务资料、订阅/账单/用量、公共题库授权、平台员工、审计和告警。
6. 所有真实 provider 密钥只配置在后端 `.env``app_private.tenant_secrets``app_private.platform_secrets` 或生产 KMS/Vault不进入 Taro。
7. 对象存储私有资源必须通过 `content_assets` 台账和后端短签名;前端只展示签名 URL、过期时间、`watermark.traceId` 和水印容器。
8. 支付页面只展示后端返回的支付参数、订单状态和权益结果;金额、套餐、优惠、权益最终以后端返回为准。
## 必跑检查
页面、API service、路由、runtime config 或发布目录有任何变化时,至少运行:
```bash
npm run check:taro
npm run test:readiness
npm run smoke:taro:h5
npm run smoke:taro:h5:interaction
node scripts/taro-h5-release-guardrails-test.js --require-dist --require-runtime-config
```
后端、RLS、provider、对象存储或生产配置有变化时还要运行
```bash
npm run readiness:production
npm run readiness:production:db
npm run smoke:auth:remote
npm run test:rls
npm run audit:runtime
```
正式上线前,三套 H5 严格发布证据、真实 Auth/RLS、真实 provider 抽样、对象存储控制、支付对账、PostgreSQL 严格调参证据和真实数据压测都要写入本地 `docs/refactor/production-launch-evidence.json`,再运行:
```bash
npm run launch:gate -- --evidence docs/refactor/production-launch-evidence.json
```
## 小程序后续兼容重点
小程序不能直接照搬 H5 假设,进入真机前要单独验收:
- `@supabase/supabase-js` 的 fetch、storage、URL、token refresh 兼容性。
- 如果兼容成本高,小程序登录只调用 `apps/api/auth/*`,由后端换取可信 session。
- 微信支付容器、订阅消息、分享参数、小程序码 tenant/referral 场景。
- KaTeX/公式渲染替代方案、题图资源字段化、PDF 预览能力和下载限制。
- 网络错误、弱网续练、本地缓存恢复、切后台/回前台 token 刷新。
## 旧前端参考边界
可以参考旧项目:
- 学生端刷题流程、答题卡、题型展示、背单词卡片、知识手册阅读、个人中心视觉。
- 微信小程序分享、支付、授权和登录交互经验。
- 租户后台/运营后台字段含义和常用工作流。
不能继承旧项目:
- PocketBase SDK 直连和旧 collection 命名。
- 前端保存或拼接用户 id、租户 id 来绕过后端鉴权。
- 前端直接写订单、权益、学习记录、错题、收藏、导入任务。
- 旧头像上传/第三方头像同步;学生头像只保留男女预设。
- 默认排行榜请求;排行榜只作为租户显式开启后的活动能力。

View File

@@ -124,8 +124,8 @@ STORAGE_REQUIRE_TENANT_PREFIX=true
1. `npm run perf:postgres:evidence` 采集默认 PostgreSQL 参数。
2.`docs/refactor/postgresql-4c16g-tuning.md` 应用 shared-host 起步值。
3. 重启 PostgreSQL 后再次 `npm run perf:postgres:evidence`
3. 重启 PostgreSQL 后执行 `PG_TUNING_PROFILE=shared-host npm run perf:postgres:evidence -- --strict --json`,确认 profile 达标、`pending_restart=0``pg_stat_statements` 可用
4.`npm run perf:api:local` 的 6/30/50/100 阶梯,只读和少量写入各一组。
5. 把摘要写入本地 `production-launch-evidence.json`,执行 `npm run launch:gate`
5. `postgres.tuning-evidence` 和 API 压测摘要写入本地 `production-launch-evidence.json`,执行 `npm run launch:gate`
容量折算不要直接把压测 worker 当在线人数。真实学生有读题和思考时间,应结合 H5 埋点估算单人平均 RPS再按成功 RPS 折算在线容量。