170 lines
5.5 KiB
Markdown
170 lines
5.5 KiB
Markdown
# scripts/ — 部署到生产机的辅助脚本
|
|
|
|
> 这些脚本不需要在生产机上跑。`prod_loadtest.sh` 是一站式包装,
|
|
> 把所有 SSH 隧道、seed、loadgen、preflight、report、cleanup 操作
|
|
> 串成子命令,本地直接调,目标始终是生产 DB / 生产网关。
|
|
|
|
---
|
|
|
|
## 📜 脚本清单
|
|
|
|
| 脚本 | 用途 | 谁要跑 |
|
|
|------|------|--------|
|
|
| **[prod_loadtest.sh](prod_loadtest.sh)** | 一站式压测:子命令模式 (`up` / `seed` / `loadgen` / `report` / `cleanup-all` / `pipeline` 等) | on-call、想跑压测的工程师 |
|
|
| [prod_seed.sh](prod_seed.sh) | ⚠️ 旧脚本:只能在生产机上跑 (SSH 进去后 `bash prod_seed.sh`) | 不推荐使用,统一改用 prod_loadtest.sh |
|
|
| [mint_reset.sh](mint_reset.sh) | mint 数据重置(每跑完一个 S4 stage 调一次) | loadgen S4 场景内部调用,不用手跑 |
|
|
|
|
---
|
|
|
|
## 🚀 快速开始 (prod_loadtest.sh)
|
|
|
|
### 一键完成整个压测流程
|
|
|
|
```bash
|
|
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
|
|
```
|
|
|
|
### 细粒度控制(推荐)
|
|
|
|
```bash
|
|
SCRIPT=./backend/scripts/loadgen/scripts/prod_loadtest.sh
|
|
|
|
# 1. 建 SSH 隧道
|
|
$SCRIPT up
|
|
|
|
# 2. 备份生产 DB
|
|
$SCRIPT backup
|
|
|
|
# 3. 灌 1000 测试用户 + 23k 行数据
|
|
$SCRIPT seed
|
|
|
|
# 4. 开压前 7 项检查
|
|
$SCRIPT preflight
|
|
|
|
# 5. 跑压测 (所有 loadgen 参数透传)
|
|
$SCRIPT loadgen \
|
|
--scenarios=S1,S2,S4 \
|
|
--stage=step --step-schedule='5,10,20' \
|
|
--duration=60s
|
|
|
|
# 6. 生成 final-report.md
|
|
$SCRIPT report
|
|
|
|
# 7. 全清压测数据 (含 users + stars,序列同步)
|
|
$SCRIPT cleanup-all
|
|
|
|
# 8. 关隧道
|
|
$SCRIPT down
|
|
```
|
|
|
|
### 查看状态(任何时候)
|
|
|
|
```bash
|
|
$SCRIPT status
|
|
# == SSH 隧道 ==
|
|
# ✅ 本地 25432 端口转发在跑 (PID: 12345)
|
|
# == 生产 DB 容器 ==
|
|
# topfans-postgres Up 22 hours (healthy) 0.0.0.0:5432->5432/tcp
|
|
# == 最近 3 次备份 ==
|
|
# pre-loadtest-20260616-2151.sql 1.2M
|
|
# == 本地 reports/ ==
|
|
# S1.json / S2.json / S4.json / final-report.md
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 子命令速查
|
|
|
|
| 子命令 | 说明 | 副作用 |
|
|
|--------|------|--------|
|
|
| `up` | 建 SSH 隧道 `本地 25432 → 生产 5432` | 启动 `ssh -f -N -L 25432:...` |
|
|
| `down` | 关 SSH 隧道 | 杀掉 ssh 进程 |
|
|
| `status` | 隧道/容器/备份/reports 状态 | 只读 |
|
|
| `backup` | 备份生产 DB → `/opt/topfans/backups/pre-loadtest-<ts>.sql` | 写生产机磁盘 |
|
|
| `seed` | 灌 1000 users + 23k 行 (通过隧道写生产 DB) | 写生产 DB |
|
|
| `preflight` | 7 项开压前检查 | 只读 |
|
|
| `loadgen [args]` | 跑压测,所有参数透传给 `./bin/loadgen --cmd=run` | 打生产网关 + 写 reports/ |
|
|
| `report` | 把 reports/ 下的 S*.json 合成 final-report.md | 写 reports/final-report.md |
|
|
| `cleanup` | 清理压测数据(**保留** users + stars) | 写生产 DB(删 rows) |
|
|
| `cleanup-all` | 全清(**含** users + stars,序列同步重置) | 写生产 DB(删 rows + setval) |
|
|
| `pipeline [args]` | `up → backup → seed → preflight → loadgen → report → cleanup-all → down` | 一条龙,loadgen args 透传 |
|
|
|
|
---
|
|
|
|
## 🔧 环境变量(可选覆盖)
|
|
|
|
```bash
|
|
PROD_HOST=root@101.132.250.62 # 默认
|
|
TUNNEL_PORT=25432 # 默认
|
|
BACKEND_DIR=... # 默认脚本所在目录的 ../../..
|
|
```
|
|
|
|
例:测不同端口:
|
|
```bash
|
|
TUNNEL_PORT=35432 $SCRIPT up
|
|
TUNNEL_PORT=35432 $SCRIPT seed
|
|
```
|
|
|
|
---
|
|
|
|
## 🛡️ 设计要点
|
|
|
|
### 1. SSH 端口转发为啥必要?
|
|
- 生产机 `topfans-postgres` 容器是 PostgreSQL **18.3**
|
|
- 本地 `pg_dump` 是 **17.4** → 版本不兼容
|
|
- 解决:seed/cleanup 走 `docker exec topfans-postgres pg_dump` 容器内跑 (版本匹配)
|
|
- `prod_loadtest.sh` 把这个细节封装在 `seed` / `cleanup` / `cleanup-all` 里
|
|
|
|
### 2. 凭据从哪来?
|
|
- 所有子命令从 `docker/.env.prod` 读 `DB_PASSWORD` / `JWT_SECRET`
|
|
- 不在命令行明文泄露
|
|
- 调用方看不到 .env.prod 文件(只要 prod_loadtest.sh 内部读)
|
|
|
|
### 3. 数据安全
|
|
- `--cleanup`(默认):保留 1000 users,只清资产(支持"多轮压测")
|
|
- `--cleanup-all`:**含** users + stars(适合"压测彻底收尾")
|
|
- 序列同步:cleanup 末尾会 `setval()` 所有相关表的 sequence(避免后续 GORM 报 duplicate key)
|
|
|
|
### 4. 为什么不用 prod_seed.sh?
|
|
- `prod_seed.sh` 需要 SSH 到生产机跑,**有歧义**(以为是 prod-only 工具)
|
|
- `prod_loadtest.sh` 全部在本地,**语义清晰**(本地调,目标生产)
|
|
- 保留 `prod_seed.sh` 是为了向后兼容(已经在生产机上跑过的人),但 README/工具集都优先推荐 `prod_loadtest.sh`
|
|
|
|
---
|
|
|
|
## 🔍 故障排查
|
|
|
|
### "本地 25432 端口未监听"
|
|
跑 `$SCRIPT up` 建隧道。
|
|
|
|
### "DB_PASSWORD 未找到"
|
|
检查 `docker/.env.prod` 是否存在并有 `DB_PASSWORD=` 行。
|
|
|
|
### preflight ③ backup 报 < 50MB
|
|
生产库本身小(几十 MB),RUNBOOK 红线是历史经验值,不是阻断错误。
|
|
|
|
### loadgen 报 `circuit breaker tripped!`
|
|
看 `loadgen-*.log` 找 `🚨 circuit breaker tripped!` 上下文:
|
|
- 如果错误率/p99 正常,可能是 `metrics-feed.jsonl` 缺失导致误 trip(已修复:`latestServer` 改 nil 判断)
|
|
- 如果是真有错,看报告里 `S*.json` 的 `errors` 字段
|
|
|
|
### SSH 隧道被挂起或断
|
|
```bash
|
|
$SCRIPT down
|
|
$SCRIPT up
|
|
```
|
|
|
|
---
|
|
|
|
## 📂 相关文件
|
|
|
|
- 上层: [../README.md](../README.md) | [../RUNBOOK.md](../RUNBOOK.md) | [../REPORT_GUIDE.md](../REPORT_GUIDE.md)
|
|
- seed 工具: [../seed/README.md](../seed/README.md)
|
|
- reports 输出: [../../reports/](../../reports/) (gitignore)
|