Files
photo-live/loadtest/README.md
T

97 lines
6.4 KiB
Markdown
Raw Normal View History

# loadtest —— k6 压测框架(P5-prep Task 3)
对齐项目计划 §6 首轮容量验证建议的 L1/L2 阶梯(L1 基础:相册 1000 照片 /
3 人上传 / 100 观众;L2 目标候选:10000 / 10 / 1000;L3 扩展探测不设默认门槛)。
**D05(数量并发与网络目标)未定——所有 thresholds 为占位注释**,确认后取消
注释启用(候选口径见 §3)。
## 文件
| 文件 | 用途 |
| --- | --- |
| `read-feed.js` | 观众读路径:N 观众(ramp 阶段)持续分页读最新 + 热门切换 + 大图请求 + 点赞批次 + 浏览上报四 mix |
| `upload-burst.js` | 工作人员 M 并发小图上传全链(presign → OSS PUT → complete),可选轮询发布可见 / ov 同步;兼作数据种子 |
| `lib/helpers.js` | 登录 / 建相册 / 上传全链 / 分页 / 点赞 / 浏览 / 轮询助手 + 内嵌 800x600 JPEG fixture(与 `scripts/prod-smoke.sh` 同源) |
安装:[k6](https://grafana.com/docs/k6/latest/set-up/install/) ≥ 0.45(Windows/
macOS/Linux 均有安装包)。脚本在仓库根 `loadtest/` 下直接 `k6 run`。
## 运行方式
```bash
# ① 种子:建时间戳相册并上传照片(L1 档:3 人 × 20 张;setup 会打印 ALBUM_TOKEN)
k6 run --env BASE_CN=https://photo.example.cn \
--env ACCOUNT=admin --env PASSWORD='…' \
--env VUS=3 --env ITERATIONS=20 upload-burst.js
# ② 观众读路径压测(L1 档:100 观众;用 ① 打印的 ALBUM_TOKEN)
k6 run --env BASE=https://photo.example.com --env ALBUM_TOKEN=<打印值> \
--env VUS=100 --env STEADY=5m read-feed.js
# ②' L2 档:观众 1000 / 上传 10 人(先种更大相册:10 × 100)
k6 run --env BASE=… --env ALBUM_TOKEN=… --env VUS=1000 --env STEADY=10m read-feed.js
# ③ 上传链含发布观测(传输完成→发布;ov 同步端到端可选)
k6 run --env BASE_CN=… --env ACCOUNT=… --env PASSWORD=… \
--env ALBUM_ID=<albumId> --env ALBUM_TOKEN=<token> \
--env WAIT_PUBLISH=1 --env WAIT_SYNC=1 --env BASE_OV=https://photo.example.com \
upload-burst.js
# 结果归档:--out json=results-$(date +%F-%H%M).json 或 --summary-export=summary.json
```
### 参数总表(--env KEY=VALUE)
| KEY | 脚本 | 缺省 | 说明 |
| --- | --- | --- | --- |
| `BASE` | 两者 | 必填(read)/ upload 的 BASE_CN 回退 | 被测 API 基址(read 用 ov 域,upload 用 cn 域),末尾不带 `/v1` |
| `ALBUM_TOKEN` | read 必填 / upload 可选 | — | 公开相册 token(种子模式首次运行打印) |
| `ACCOUNT` / `PASSWORD` | upload | 必填 | 工作人员(或 admin)账号 |
| `ALBUM_ID` | upload | 空=建新册 | 复用相册;配合 `ALBUM_TOKEN` 才有发布轮询 |
| `VUS` | 两者 | 100 / 3 | 观众数 / 上传并发人数 |
| `ITERATIONS` | upload | 20 | 每人上传张数(L1 合计 = VUS×ITERATIONS) |
| `STEADY` / `RAMP_UP` / `RAMP_DOWN` | read | 5m / 1m / 1m | ramp 阶段时长 |
| `PAGES` / `PAGE_LIMIT` | read | 3 / 30 | 翻页深度 / 页大小(契约上限 60) |
| `HOT_SHARE` / `BIGIMG_SHARE` / `LIKE_SHARE` | read | 0.5 / 0.3 / 0.4 | 迭代内行为混合概率 |
| `THINK_MIN` / `THINK_MAX` | read | 0.5 / 3 | 观众思考时间秒 |
| `WAIT_PUBLISH` / `WAIT_SYNC` / `BASE_OV` | upload | 0 / 0 / 空 | 公开可见轮询开关(cn 发布 / ov 同步) |
| `POLL_TIMEOUT` / `POLL_INTERVAL` | upload | 60 / 2 | 轮询上限/间隔秒 |
## 输出解读(P95 关注点 ←→ 项目计划 §6 候选指标)
| 候选指标(计划原文) | k6 指标名 | 说明 |
| --- | --- | --- |
| 普通列表 API P95 < 500ms | `feed_list_duration` / `feed_hot_duration` | 按 tag `list_public_photos(_hot)` 分组的 Trend;「首批照片 P95<3s」是浏览器端口径(含渲染/图载),k6 以首页列表请求近似 + §冷缓存另测 |
| 传输完成到发布 P95 < 10s | `publish_wait_duration` | `WAIT_PUBLISH=1` 时 complete → cn 公开列表可见的等待;上传耗时(`upload_oss_put_duration`)单独统计,不计入处理时延(计划注记) |
| (同上,跨境) | `ov_sync_wait_duration` | `WAIT_SYNC=1`:complete → ov 公开可见(含推送 2s 间隔) |
| 点赞确认及广播 P95 < 2s | `like_confirm_duration` | API 确认口径;WS 广播时延属前端观测面,k6 不覆盖 |
| — | `upload_presign_duration` / `upload_complete_duration` | 上传链分步;`upload_chain_duration` 为三步端到端 |
| — | `like_rejected_total` / `publish_timeout_total` | 非目标信号:前者多为限速触发(见下),后者=发布超时需查 worker |
通用看板项:`http_req_duration`(按 name tag 细分)、`http_req_failed`、
`checks` 通过率、VU 数与迭代吞吐(`iteration_duration` 倒数)。**冷缓存/地域
时延不在 k6 范围**——用 `infra/deploy/cdn-checklist.md` §6 的多地域 curl 记录表。
## 阈值占位(D05 确认后启用)
两脚本 `options.thresholds` 均为注释占位(候选值即上表)。确认 D05 后:
1. 取消注释并按定案值调整;
2. L2 档跑 `k6 run … --tag testid=l2-$(date +%F)` 便于结果对比归档;
3. 阈值失败会让 k6 以非零码退出——可直接作为 P5 容量报告的机器判定。
## 操作注意(如实阅读再跑)
- **限速会污染指标**:likes 有 Redis 滑窗限速(`LIKE_IP_WINDOW_DELTA=2000` /
24h / IP;`LIKE_SESSION_WINDOW_DELTA=500` / 会话)——高并发点赞从单一压测机
出发很快触发 429(计入 `like_rejected_total`,且账面不是真实服务容量)。
staging 压测调大对应 env 或 `LIKE_SHARE=0`;需要真实验证限速本身时反向利用。
visits 的键含 visitorId(每 VU 唯一),`VISIT_WINDOW_REQUESTS=60`/窗 通常够用。
- **反代后 IP 归并**:经 OpenResty 反代时服务端 req.ip 是网关地址,trust proxy
未配置前所有限速按网关 IP 聚合——压测读数要意识到这一点(登记为 P5 项,
likes.controller.ts 文件头同注)。
- **对象存储是外部依赖**:`oss_put` / `oss_image_get` 打到 MinIO/OSS/CDN 直链,
其时延与被测 API 分开解读(tag 已区分);生产桶上跑会产生真实流量费用。
- **不自动清理**:种子照片留在相册内(时间戳标题可辨认),清理=后台软删或
`DELETE /v1/photos/{id}`(prod-smoke 同款);相册无删除端点。
- 对生产环境执行前必须获得明确许可——上传/点赞/浏览写路径全部落真实数据。