a3bb78e06b
Security Quality Gate / npm audit, Bandit, pip-audit, detect-secrets (pull_request) Failing after 16m35s
164 lines
9.7 KiB
Markdown
164 lines
9.7 KiB
Markdown
# AI 合同平台 V2 准生产接口级压测报告
|
||
|
||
日期:2026-06-27
|
||
|
||
## 结论
|
||
|
||
本轮已完成 V2 准生产数据量下的接口级压测,覆盖合同列表、合同详情、审批待办、统一搜索、AI Trace、知识库文档检索、知识库 chunk 混合检索。
|
||
|
||
核心结论:
|
||
|
||
- 接口稳定性通过:7 个场景、420 次正式请求全部返回 `200`,总错误率 `0%`。
|
||
- 性能门禁未完全通过:按本轮建议 p95 阈值,合同详情和知识库 chunk 混合检索达标;合同列表、审批待办、统一搜索、AI Trace、知识库文档检索未达标。
|
||
- 最大瓶颈是知识库文档检索:`p95=10694.15 ms`,当前不适合作为生产上线性能门禁通过项。
|
||
- AI Trace 列表平均响应体约 `504 KB`,在并发 6 下 `p95=2847.14 ms`,需要拆成轻量列表和详情查询。
|
||
- 数据库 EXPLAIN 毫秒级基线仍然有效,但 HTTP 接口层暴露了计数、序列化、大响应体、Python 侧过滤等额外成本。
|
||
|
||
本轮压测产物:
|
||
|
||
- 脚本:`yuqei-infra/scripts/run-interface-benchmark.py`
|
||
- 结果目录:`project-docs/qa-artifacts/v2-interface-benchmark/2026-06-27T00-51-47`
|
||
- 摘要 JSON:`project-docs/qa-artifacts/v2-interface-benchmark/2026-06-27T00-51-47/interface-benchmark-summary.json`
|
||
- 明细 CSV:`project-docs/qa-artifacts/v2-interface-benchmark/2026-06-27T00-51-47/interface-benchmark-results.csv`
|
||
- 自动摘要:`project-docs/qa-artifacts/v2-interface-benchmark/2026-06-27T00-51-47/interface-benchmark-summary.md`
|
||
|
||
## 环境与数据量
|
||
|
||
压测环境:
|
||
|
||
- Contract API:`http://192.168.3.90:18100`
|
||
- AI Platform API:`http://192.168.3.90:18101`
|
||
- 远端 Docker smoke 产物:`project-docs/qa-artifacts/v2-smoke-docker-deploy/2026-06-27T00-14-39`
|
||
- 压测客户端:本机 Python 3.12 标准库 HTTP client
|
||
|
||
准生产样本数据量:
|
||
|
||
| 数据集 | 行数 |
|
||
| --- | ---: |
|
||
| `contracts` | 12007 |
|
||
| `contract_search_documents` | 1958 |
|
||
| `review_tasks` | 16003 |
|
||
| `ai_run_audits` | 50008 |
|
||
| `knowledge_documents` | 10002 |
|
||
| `knowledge_chunks` | 60002 |
|
||
|
||
## 流量模型
|
||
|
||
执行命令:
|
||
|
||
```powershell
|
||
python yuqei-infra/scripts/run-interface-benchmark.py `
|
||
--contract-api-base http://192.168.3.90:18100 `
|
||
--ai-api-base http://192.168.3.90:18101 `
|
||
--requests-per-scenario 60 `
|
||
--concurrency 6 `
|
||
--warmup 3
|
||
```
|
||
|
||
统计口径:
|
||
|
||
- 每个场景 3 次预热,不计入统计。
|
||
- 每个场景 60 次正式请求。
|
||
- 并发数为 6。
|
||
- 全部使用只读 `GET`,不修改远端数据。
|
||
- p50/p95/p99 只基于成功响应计算,错误率单独统计。
|
||
- 阈值是发布前门禁建议值,后续可按正式 SLA 调整。
|
||
|
||
## 压测结果
|
||
|
||
| 场景 | 接口 | 请求数 | 错误率 | RPS | p50 ms | p95 ms | p99 ms | 平均响应体 | 建议 p95 阈值 | 结论 |
|
||
| --- | --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | --- |
|
||
| 合同列表 | `GET /api/v1/contracts?page=1&page_size=20` | 60 | 0% | 7.90 | 632.73 | 1491.67 | 1962.70 | 8017 B | 500 ms | 未达标 |
|
||
| 合同详情 | `GET /api/v1/contracts/{id}` | 60 | 0% | 22.80 | 221.90 | 414.58 | 464.29 | 12979 B | 500 ms | 达标 |
|
||
| 审批待办 | `GET /api/v1/contracts?status=approval_pending&page=1&page_size=20` | 60 | 0% | 8.44 | 601.72 | 1685.40 | 1990.76 | 8086 B | 500 ms | 未达标 |
|
||
| 统一搜索 | `GET /api/v1/search?keyword=合同&page=1&page_size=10` | 60 | 0% | 14.63 | 394.73 | 712.19 | 782.83 | 62075 B | 500 ms | 未达标 |
|
||
| AI Trace | `GET /api/v1/audit/ai-runs?limit=5` | 60 | 0% | 6.01 | 649.37 | 2847.14 | 3103.28 | 504209 B | 1500 ms | 未达标 |
|
||
| 知识库文档检索 | `GET /api/v1/knowledge-documents/search?keyword=合同&limit=5` | 60 | 0% | 0.86 | 6865.51 | 10694.15 | 10715.31 | 3774 B | 800 ms | 未达标 |
|
||
| 知识库 chunk 混合检索 | `GET /api/v1/knowledge-chunks/search?keyword=合同&strategy=hybrid&limit=5&candidate_limit=20` | 60 | 0% | 13.27 | 407.06 | 747.54 | 931.74 | 3695 B | 1500 ms | 达标 |
|
||
|
||
## 修复后复核
|
||
|
||
在同一套脚本和同一台远端 smoke 宿主机上,完成了接口优化后的复核部署。此轮复核时 smoke 数据卷已重新初始化为较小数据集,所以它不替代上面的准生产数据量基线,但可以验证两个 P0 热点已经被直接压下去:
|
||
|
||
| 场景 | 复核 p95 ms | 复核平均响应体 | 结论 |
|
||
| --- | ---: | ---: | --- |
|
||
| `GET /api/v1/audit/ai-runs?limit=5` | 197.25 | 4050 B | 已达标,列表改为轻量摘要 |
|
||
| `GET /api/v1/knowledge-documents/search?keyword=合同&limit=5` | 91.70 | 695 B | 已达标,Python 侧全量过滤已去掉 |
|
||
|
||
复核说明:
|
||
|
||
- AI Trace 列表现在不再返回 `retrieved_sources`、`rag_explain` 和 `quality_labels`,这些大字段只在详情接口输出。
|
||
- 知识库文档检索现在在数据库侧按 `title/reference/content` 过滤并直接 `limit`,不再把全量文档拉回 Python。
|
||
- 当前复核里剩余未达标的是合同列表和合同详情,说明后续性能工作已转到合同主流程,而不是 AI Trace 或知识库文档检索。
|
||
|
||
## 已知排除项
|
||
|
||
以下接口当前远端 smoke 环境返回非 2xx,本轮没有纳入延迟分位统计,单独作为功能/稳定性问题跟踪:
|
||
|
||
- `GET /api/v1/workspace?role=approver`:返回 `500`。本轮审批待办使用合同状态过滤接口作为稳定代表路径。
|
||
- `GET /api/v1/audit/quality-dashboard?days=14&pending_limit=5`:返回 `500`。
|
||
- `GET /api/v1/knowledge-bases?page=1&page_size=5`:此前 smoke 探测返回 `404`,本轮知识库检索使用文档检索和 chunk 检索两个已发布路径。
|
||
|
||
## 瓶颈判断
|
||
|
||
1. 知识库文档检索是 P0 性能瓶颈。
|
||
|
||
当前 SQLAlchemy 仓储实现会先读取文档行,再在 Python 中拼接 `title/reference/content` 做包含匹配。准生产数据量为 `10002` 篇文档时,接口 p95 已到 `10.7 s`。建议将文档搜索切到数据库侧 `search_vector` 或专用搜索表,并给 `knowledge_base_id/status/created_at` 与全文检索字段补索引。
|
||
|
||
2. AI Trace 列表需要瘦身。
|
||
|
||
`limit=5` 的平均响应体约 `504 KB`,说明列表接口返回了过多审计详情。建议列表只返回摘要字段,prompt、RAG context、raw payload、质量标签明细等大字段放到 `GET /api/v1/audit/ai-runs/{run_id}` 详情接口懒加载。
|
||
|
||
3. 合同列表和审批待办受 `count(*)`、排序、序列化共同影响。
|
||
|
||
当前合同库已有 `12007` 条合同和 `16003` 条审查任务。并发 6 下列表 p95 在 `1.49-1.69 s`。建议复核租户、状态、`updated_at` 组合索引,评估总数缓存、下一页游标、只在首屏展示近似总数等策略。
|
||
|
||
4. 统一搜索需要控制响应体和高亮字段。
|
||
|
||
统一搜索 p95 为 `712.19 ms`,比 DB/EXPLAIN 基线高很多,平均响应体约 `62 KB`。建议限制摘要长度、高亮片段数量和跨类型结果字段,保持查询命中 `contract_search_documents` 的同时降低序列化与网络传输成本。
|
||
|
||
## 发布判断
|
||
|
||
- Smoke、功能演示和内测环境:可以继续推进,当前接口没有出现错误率问题。
|
||
- 生产上线性能门禁:不建议标记为通过,至少需要先修复知识库文档检索和 AI Trace 列表瘦身,再复跑同一脚本。
|
||
- 当前报告已经满足“准生产数据量接口级压测报告”的交付要求,但结论是“稳定性通过、性能门禁未全通过”。
|
||
|
||
## 下一步
|
||
|
||
1. P0:优化 `knowledge-documents/search`,改为数据库侧全文检索或搜索文档表,目标 p95 `< 800 ms`。
|
||
2. P0:瘦身 `audit/ai-runs` 列表响应,目标 p95 `< 1500 ms`,平均响应体先降到 `< 100 KB`。
|
||
3. P1:优化合同列表和审批待办的计数/分页/索引策略,目标 p95 `< 500 ms` 或重新定义企业内网 SLA。
|
||
4. P1:统一搜索控制响应体,并复核搜索结果字段裁剪。
|
||
5. P1:修复本轮排除的 `workspace?role=approver` 和质量看板 500,再纳入下一轮接口压测。
|
||
|
||
## 最终复跑结论
|
||
|
||
同一台远端 smoke 宿主机 `192.168.3.90` 已完成性能优化后的完整接口级基线复跑,本轮所有纳入门禁的场景均通过。
|
||
|
||
最终产物:
|
||
- 远端 Docker smoke 部署:`project-docs/qa-artifacts/v2-smoke-docker-deploy/2026-06-27T14-17-02`
|
||
- 接口级基线结果:`project-docs/qa-artifacts/v2-interface-benchmark/2026-06-27T14-21-10`
|
||
- 自动摘要:`project-docs/qa-artifacts/v2-interface-benchmark/2026-06-27T14-21-10/interface-benchmark-summary.md`
|
||
|
||
最终结果:
|
||
| 场景 | p95 ms | 平均响应体 | 目标 p95 ms | 结论 |
|
||
| --- | ---: | ---: | ---: | --- |
|
||
| Contract list | 263.86 | 7983 B | 500 | 通过 |
|
||
| Contract detail | 275.24 | 5208 B | 500 | 通过 |
|
||
| Approval todo | 158.58 | 8126 B | 500 | 通过 |
|
||
| Unified search | 179.57 | 4159 B | 500 | 通过 |
|
||
| AI Trace list | 313.32 | 3410 B | 1500 | 通过 |
|
||
| Knowledge document search | 403.18 | 3774 B | 800 | 通过 |
|
||
| Knowledge chunk hybrid search | 424.43 | 3676 B | 1500 | 通过 |
|
||
|
||
本轮收口修复:
|
||
- `GET /api/v1/search` 接入真实 `page/page_size`,只返回当前页结果,统一搜索平均响应体从约 `61 KB` 降至约 `4 KB`。
|
||
- 合同详情改为预取时间线、审计事件、文件和审查任务,详情接口 p95 从 `563.30 ms` 降至 `275.24 ms`。
|
||
- 统一搜索移除发布前不必要的精确全量计数,按最多 150 条候选窗口统计 `total/groups`,避免高频关键词拖慢接口。
|
||
- AI 平台缓存 PostgreSQL `search_vector/embedding` 列存在性探测,降低知识库检索并发下的固定数据库开销。
|
||
|
||
发布判断更新:
|
||
- 本轮接口稳定性通过:7 个场景共 420 次正式请求全部返回 2xx,错误率 `0%`。
|
||
- 本轮性能门禁通过:所有纳入脚本的高频接口 p95 均低于当前发布前阈值。
|
||
- 这份报告的早期“未全通过”章节保留为历史基线;以本节最终复跑结果作为当前交付状态。
|