Why: Checklist B6 needs a repeatable database-only baseline that cannot reach production ports or instances. Evidence: run_pgbench.sh --self-check passed (help, unknown arg, foreign name, busy port, SIGINT cleanup). Timed runs are recorded separately. Impact: New load-test entry and README note. No product or release-gate change. Refs: docs/release-multi-instance.md B6 Co-authored-by: Cursor <cursoragent@cursor.com>
87 lines
4.5 KiB
Markdown
87 lines
4.5 KiB
Markdown
# 协作存储压测套件(U7 / B5 / C2)
|
||
|
||
方案 §3 负载合同 / §5 U7 的业务压测入口。**只打隔离栈**(自建 PG 实例 +
|
||
mock 模式 backend),绝不打生产服务;模拟模型(mock)用于容量基线,真实
|
||
模型的全链路验证按方案另行小流量执行。
|
||
|
||
## 组成
|
||
|
||
| 文件 | 职责 |
|
||
|---|---|
|
||
| `run_load.sh` | 编排入口:起隔离栈 → 可选 seed → 引导账号 → k6 → SSE 探针 → 不变量对账 → 回收 |
|
||
| `seed/` | B5 大数据量种子(PG `COPY`:messages/events/knowledge;tiny / contract) |
|
||
| `k6/collab_api.js` | 混合读写负载;双实例时 `BASE_URLS` VU 粘滞 + 跨实例读 + 热点会话 409 |
|
||
| `sse_probe/` | SSE 持久事件可见延迟探针(Go);双实例时对 A/B 各跑一份 |
|
||
| `results/<ts>/` | 原始输出:`k6-summary.json`、`sse-probe-a.json`(及 `-b`)、`seed-manifest.json`、`invariants.txt` |
|
||
|
||
## 快速开始
|
||
|
||
```bash
|
||
# 冒烟(~2 分钟,无需 k6——缺失时自动跳过 k6 段并给出安装指引)
|
||
tests/load/collaboration/run_load.sh --profile smoke
|
||
|
||
# B5 tiny seed + 单实例冒烟(接线验证,秒级灌库)
|
||
tests/load/collaboration/run_load.sh --profile smoke --seed tiny
|
||
|
||
# C2 双实例冒烟(共享 PG/artifacts;VU 分摊两址)
|
||
tests/load/collaboration/run_load.sh --profile smoke --seed tiny --instances 2
|
||
|
||
# 阶梯(10→30→100 VU,~12 分钟;k6: brew install k6)
|
||
tests/load/collaboration/run_load.sh --profile ladder --users 30
|
||
|
||
# 长稳(60 分钟 / 2 小时混合)
|
||
tests/load/collaboration/run_load.sh --profile sustained60m
|
||
tests/load/collaboration/run_load.sh --profile sustained2h
|
||
|
||
# 负载合同满量 seed(约 100 万消息 + 10 万知识;数分钟与数 GB 磁盘,视机器)
|
||
tests/load/collaboration/run_load.sh --seed contract --profile smoke --skip-k6 --skip-probe --keep
|
||
# 或只跑 seed 二进制(库须已迁移且 seed_u* 已 CLI 建号):
|
||
# .build/seed --dsn "$APP_DSN" --profile contract --manifest /tmp/seed-manifest.json
|
||
|
||
# 复用已有隔离 PG;保留栈便于复查
|
||
tests/load/collaboration/run_load.sh --dsn 'postgresql://…/agent' --keep
|
||
```
|
||
|
||
## `--seed` 档位
|
||
|
||
| profile | 用户 | 项目/用户 | 会话/项目 | messages(+events) | knowledge | 用途 |
|
||
|---|---|---|---|---|---|---|
|
||
| `none` | — | — | — | 0 | 0 | 默认;空库压测 |
|
||
| `tiny` | 3 | 2 | 2 | 1 000 | 1 000 | 接线冒烟(秒级) |
|
||
| `contract` | 10 | 5 | 10 | 1 000 000 | 100 000 | 方案 §3 数据量档 |
|
||
|
||
- 约 10% knowledge 行 `owner=''`(基座共享知识语义);**不写** `knowledge_vectors`
|
||
(进程内向量扫描面向数万块;100 万分块扩展档另档)。
|
||
- 交叉授权:数据集含多用户多项目 + 共享分块;EXT-8 `ResourceAuthorizer` 矩阵
|
||
仍由检查单 A7 覆盖,本入口不注入 load-only 授权后门。
|
||
- `contract` 耗时/磁盘随机器变化;正式容量结论须绑定组件 SHA 与
|
||
`results/<ts>/seed-manifest.json`,不预填。
|
||
|
||
## `--instances`(C2)
|
||
|
||
| 值 | 行为 |
|
||
|---|---|
|
||
| `1`(默认) | 单 serve:`u7load-a` @ `--port`(默认 18980) |
|
||
| `2` | 双 serve 共享同一 `APP_DSN` 与 artifacts;B @ `--port-b`(默认 **18982**,避开隔离 PG 18981) |
|
||
|
||
双实例时 k6 注入 `BASE_URLS=a,b`:VU 粘滞到实例、跨实例读抽样、热点会话
|
||
跨实例写计入 `expected_contention`(409)。非热点会话读路径仍受
|
||
P95≤300ms 阈值约束——「互相不拖累」的可机判口径。SSE 探针对 A/B 各跑一份。
|
||
|
||
## 阈值与口径(负载合同,待实测校准)
|
||
|
||
- 非模型普通 API:读路径 P95≤300ms、P99≤1s(k6 threshold 按 `read` 组单列)。
|
||
- 非预期失败率≤0.1%(`http_req_failed<0.001`);预期拥塞(会话忙 409 /
|
||
队列满 429)记入 `expected_contention`,**不**计入失败。
|
||
- SSE 持久事件可见延迟 P95≤1s + seq 零乱序(探针退出码即断言)。
|
||
- 数据不变量零违反:events 每会话 seq 无重复(SQL 对账,违反即 exit 1)。
|
||
|
||
## 边界(诚实声明)
|
||
|
||
- 正式 60min/2h 窗口、双主机(C3)、`contract` 满量压测窗口需用户指定资源与时间;
|
||
本仓提供可复核入口,不预填容量结论。
|
||
- `pgbench` 只测数据库能力,不替代站点业务验收(方案 §5 U7)。入口是
|
||
`run_pgbench.sh`(检查单 B6):隔离实例 `u7bench`、端口 18995、scale 100,
|
||
select-only 与 TPC-B 各跑 10/30/100 客户端。没有业务阈值;结果是参考基线。
|
||
- k6 缺失时跳过 k6 段并写 `k6-skipped.txt`;探针与对账仍跑。
|