9.3 KiB
9.3 KiB
后端服务压测工具 (loadgen)
给阿里云单机 (4G/2C) TopFans 后端微服务用的压测 + 数据准备工具集。 凌晨 02:00-06:00 业务低峰执行,数据物理隔离
star_id=999900。
📚 文档地图
| 文档 | 用途 | 谁要看 |
|---|---|---|
| README.md (本文) | 工具集概览 + 5 分钟入门 | 所有人 |
| RUNBOOK.md | 凌晨压测一步一步操作手册 | on-call 工程师 |
| REPORT_GUIDE.md | 压测报告怎么读 + 瓶颈定位 + 行动项模板 | 看报告的工程师 / TL |
| seed/README.md | seed 工具细节 (数据准备) | 第一次跑压测的人 |
🧰 工具集概览
loadgen/
├── seed/ # 数据准备 CLI (生成 1000 个测试用户 + 资产 + JWT)
├── loadgen/ # 压测主程序 (7 个场景,6 维熔断,带 reporter)
├── monitor/ # 监控栈 (Prometheus + Grafana,可选)
├── recover/ # 紧急灭火 (一键停 + 数据库恢复)
├── scripts/ # 部署到 prod 的辅助脚本
└── reports/ # 跑测产出 (gitignore,scp 拉回本地)
核心 CLI: bin/seed + bin/loadgen
| 命令 | 作用 |
|---|---|
./bin/seed |
灌测试数据 → users.csv + 数据库 |
./bin/seed --cleanup |
清理测试数据 (保留 1000 用户) |
./bin/seed --cleanup --full |
全部删掉 (账号本身) |
./bin/seed --reset-tokens |
只重签 JWT (跨周压测用) |
./bin/loadgen --cmd=preflight |
7 项开压前检查 |
./bin/loadgen --cmd=run --scenarios=S1 |
跑场景 |
./bin/loadgen --cmd=report |
生成 markdown 报告 + PNG 图表 |
7 个场景
| ID | 场景 | 默认 RPS | 写/读 | 关键 API |
|---|---|---|---|---|
| S1 | Login | 15 | 写(轻) | POST /api/v1/auth/login |
| S2 | Read | 250 | 读 | GET /api/v1/assets/{id} |
| S3 | Like | 50 | 写(轻) | POST/DELETE /api/v1/social/assets/{id}/like |
| S4 | Mint | 1-5 | 写(重) | POST /api/v1/assets/mints/precreate |
| S5 | Dashboard | — | 读聚合 | (dashboard 聚合) |
| S6 | Ranking | 300 | 读 | GET /api/v1/rankings/hot |
| S7 | Place | 1-5 | 写(重) | (摆展事务) |
⭐ 推荐入口:prod_loadtest.sh 一键脚本
如果你的目标是打生产压测(无论 prod 还是本地 docker),优先用
scripts/prod_loadtest.sh。 子命令模式覆盖了全部流程,凭据从docker/.env.prod读,避免明文泄露。
cd /Users/liulujian/Documents/code/TopFansByGithub
# 一键:up → backup → seed → preflight → loadgen → report → cleanup-all → down
./backend/scripts/loadgen/scripts/prod_loadtest.sh pipeline \
--scenarios=S1,S2,S4 --stage=step --step-schedule='5,10,20' --duration=60s
完整子命令、状态查询、故障排查见 scripts/README.md。
🚀 5 分钟入门 (本地 docker)
# 1. 编译 (Linux prod 部署用,本地 darwin 直接 go build)
cd backend
make loadgen-build
# 2. 准备数据 (需要本地 docker postgres)
cd scripts/loadgen/seed
# 生成 bcrypt 哈希 (与 tokens.go 硬编码的 "Test@123" 匹配)
python3 -c "import bcrypt; print(bcrypt.hashpw(b'Test@123', bcrypt.gensalt(rounds=10)).decode())" \
> loadtest_bcrypt.txt
# 跑 seed (用本地 docker 的 env)
DB_PASSWORD=123456 \
JWT_SECRET=topfans-secret-key-local-dev-only \
/Users/liulujian/Documents/code/TopFansByGithub/backend/bin/seed \
--db-name=top-fans --db-host=localhost --db-port=15432 --db-user=postgres
# 3. 复制 users.csv 到 backend 目录
cp users.csv ../../../users.csv
# 4. 开压前检查
cd ../../../ # = backend
JWT_SECRET=topfans-secret-key-local-dev-only \
./bin/loadgen --cmd=preflight --target=http://localhost:8080
# 5. 烟雾测试 (30 秒,1 RPS)
JWT_SECRET=topfans-secret-key-local-dev-only \
./bin/loadgen --cmd=run --scenarios=S1 --stage=baseline --rps=1 --duration=30s \
--target=http://localhost:8080 --monitor=off
# 6. 生成报告
JWT_SECRET=topfans-secret-key-local-dev-only \
./bin/loadgen --cmd=report --input=./reports --output=./reports/final-report.md
open reports/final-report.md # macOS
🔨 编译
cd backend
make loadgen-build # 编译 seed + loadgen 到 bin/
make loadgen-test # 单元测试 (23 个)
make loadgen-vet # go vet
make loadgen-ci # vet + test + build (CI 单步)
手动编译 (Linux prod):
GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o bin/seed ./scripts/loadgen/seed/
GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o bin/loadgen ./scripts/loadgen/loadgen/
🛡️ 安全设计
数据隔离
所有测试数据用 star_id = 999900 物理隔离,不影响真实业务 star_id (87, 88, 91, 93, 94, 95)。
CLAUDE.md 序列重置
seed 工具末尾自动同步所有相关表的 PG 序列(避免后续 GORM 插入报 duplicate key)。
凌晨窗口
执行窗口:02:00 - 06:00 业务低峰。
紧急灭火: recover/emergency-stop.sh 一键停 + restore-from-backup.sh 5-8min 还原。
6 维红线熔断 (自动停)
| # | 红线 | 阈值 | 数据源 |
|---|---|---|---|
| R1 | 客户端错误率 | > 5% 持续 30s | loadgen HDR |
| R2 | 客户端 P99 | > 3000ms 持续 30s | loadgen HDR |
| R3 | 5xx 比例 | > 10% 持续 10s | loadgen status |
| R4 | PG 连接数 | > 42 持续 30s | metrics-feed |
| R5 | 磁盘空闲 | < 5GB 持续 30s | metrics-feed |
| R6 | OOM 事件 | 瞬时触发 | metrics-feed |
📊 报告产出
跑完 + --cmd=report 后,reports/ 下:
reports/
├── S1.json # 原始数据 (含 stages)
├── S2.json
├── S4.json
├── baseline.csv # Excel 友好的汇总
├── s1.png # RPS / P99 / Error 曲线
├── s2.png
├── s4.png
└── final-report.md # ← 主要看这个
final-report.md 包含:
- 总览表 (所有场景一行一个,7 列)
- 每个场景的 ⚠️ 拐点 RPS (自动算:第一个 p99 涨 >50% 的 stage)
- 阶梯结果表 (每 stage 的 RPS / p50 / p95 / p99 / err / 5xx)
- PNG 曲线图 (RPS / P99 / Error 三条线)
详细读法见 REPORT_GUIDE.md。
🧪 测试状态
seed: 5/5 PASS
loadgen/lib: 16/16 PASS
scenarios: 2/2 PASS
TOTAL: 23/23 PASS
📁 完整目录
backend/scripts/loadgen/
├── README.md # ← 你在这里
├── RUNBOOK.md # ← 凌晨压测操作手册
├── REPORT_GUIDE.md # ← 报告怎么读
├── seed/ # 数据准备工具
│ ├── main.go # CLI 入口
│ ├── stars.go users.go profiles.go assets.go
│ ├── slots_and_exhibits.go friendships.go
│ ├── tokens.go sequences.go cleanup.go
│ ├── seed_test.go # 单元测试
│ ├── loadtest_bcrypt.txt # Test@123 哈希 (与 tokens.go 匹配)
│ └── README.md
├── loadgen/ # 压测主程序
│ ├── main.go # CLI 入口
│ ├── preflight.go verify.go # 7 项开压前检查 + 压后验证
│ ├── lib/ # 核心库
│ │ ├── csv.go # users.csv 解析
│ │ ├── client.go # HTTP client
│ │ ├── hdr.go # 延迟直方图 + per-stage 计数
│ │ ├── log.go ramp.go # 日志 + 阶梯调度
│ │ ├── circuit.go # 6 维熔断
│ │ ├── ssh_metrics.go # prod server metrics 抓取
│ │ ├── config.go
│ │ └── *_test.go # 16 个测试
│ ├── scenarios/ # 7 个场景
│ │ ├── s1_login.go
│ │ ├── s2_read.go
│ │ ├── s3_like.go
│ │ ├── s4_mint.go # 支持多 stage
│ │ ├── s5_dashboard.go
│ │ ├── s6_ranking.go
│ │ ├── s7_place.go
│ │ ├── common.go # doRequest + DefaultBaseURL
│ │ ├── scenarios.go # 注册表
│ │ ├── helpers.go
│ │ └── scenarios_test.go
│ └── reporter/ # 报告生成
│ ├── json.go # RunReport + StageReport
│ ├── csv.go # baseline.csv
│ ├── plot.go # PNG 曲线 (gonum)
│ ├── markdown.go # final-report.md
│ └── knee.go # KneeRPS 自动算
├── monitor/ # 监控栈 (可选)
│ ├── sample.sh # 后台采样到 metrics-feed.jsonl
│ ├── docker-compose.monitor.yml
│ ├── prometheus.yml
│ └── grafana-dashboards/ # 4 个预置面板
├── recover/ # 紧急灭火
│ ├── emergency-stop.sh
│ └── restore-from-backup.sh
├── scripts/ # prod 辅助
│ ├── mint_reset.sh # S4 之间的 mint 数据清理
│ └── prod_seed.sh # 一键跑 seed (读 prod env)
└── reports/ # 跑测产出 (gitignore)
详细设计
- 设计文档:
docs/superpowers/specs/2026-06-12-load-testing-design.md - 实施计划:
docs/superpowers/plans/2026-06-12-load-testing.md - seed 工具说明: seed/README.md