# 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 均低于当前发布前阈值。 - 这份报告的早期“未全通过”章节保留为历史基线;以本节最终复跑结果作为当前交付状态。