docs: add dual-host pressure test runbook
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
|
||||
## 1. 测试目标
|
||||
|
||||
> 双机实际操作以 [`loadtest/im-pressure/README.md`](../loadtest/im-pressure/README.md) 为准。当前开发机固定为机器 A,负责数据准备、协调器、agent A、集中采集和最终报告;另一台机器固定为机器 B,只运行 agent B 并回传结果。
|
||||
|
||||
本次测试使用 006 商户的 2000 个账号,在两台压测机上各运行 1000 个在线 WebSocket 用户,验证多 Pod 场景下:
|
||||
|
||||
1. 1000 对 P2P 会话同时收发时,消息是否被接受、实时投递并最终持久化。
|
||||
|
||||
+140
-27
@@ -2,6 +2,44 @@
|
||||
|
||||
该工具按商户 `006` 的固定模型运行:两台压测机各承载 1000 个 WebSocket 用户,共 2000 个用户、1000 对好友和一个 2000 人群。
|
||||
|
||||
## 两台机器的固定分工
|
||||
|
||||
当前仓库所在机器固定作为 **机器 A**。两台机器不要交换 `-machine` 参数,否则账号分片和结果归属会混乱。
|
||||
|
||||
| 项目 | 机器 A(当前机器,主控) | 机器 B(另一台机器,发压) |
|
||||
|---|---|---|
|
||||
| 模拟账号 | `lta0001` 至 `lta1000` | `ltb0001` 至 `ltb1000` |
|
||||
| WS 连接数 | 1000 | 1000 |
|
||||
| 固定参数 | `-machine a` | `-machine b` |
|
||||
| 数据准备 | 执行 `prepare`、`verify` | 不执行 |
|
||||
| 双机协调 | 运行 `coordinator :8090` | 连接机器 A 的 `:8090` |
|
||||
| 场景发压 | 运行 agent A | 运行 agent B |
|
||||
| 指标 | agent `:9105`,运行中央 `collect` | agent `:9105`,供机器 A 抓取 |
|
||||
| 结果 | 保存 A 结果、接收 B 结果、执行 `merge` | 保存 B 结果并传回机器 A |
|
||||
|
||||
机器 A 至少准备三个终端:协调器、agent A、指标采集。机器 B 至少准备一个终端运行 agent B;需要单独采集本机指标时再开第二个终端。
|
||||
|
||||
### 机器 B 最短操作清单
|
||||
|
||||
把本 README 放到机器 B 后,机器 B 操作人只需完成以下事项:
|
||||
|
||||
1. 检出与机器 A 相同的 Git 提交并构建 `im-pressure`。
|
||||
2. 接收机器 A 生成的 `config.json` 和 `manifest.json`,不要自行运行 `prepare`。
|
||||
3. 设置与机器 A 相同的 `IM_API_KEY`、`IM_LOAD_PASSWORD`,执行一次 `verify`。
|
||||
4. 从机器 A 获取本轮 `RUN_ID` 和机器 A 内网 IP。
|
||||
5. 等机器 A 启动 coordinator 后,固定使用 `-machine b` 启动 agent B。
|
||||
6. agent B 退出后,将 `agent-b-summary.json` 传回机器 A。
|
||||
|
||||
机器 B 不负责建账号、加好友、建群、选择场景或合并报告。
|
||||
|
||||
### 网络要求
|
||||
|
||||
- 机器 B 必须能访问 `http://机器A内网IP:8090`。
|
||||
- 如果由机器 A 集中采集 agent 指标,机器 A 必须能访问 `http://机器B内网IP:9105/metrics`。
|
||||
- 两台机器都必须能访问配置中的 HTTP API 和各自的 WS 地址。
|
||||
- `8090` 是无鉴权的压测协调端口,只允许压测内网访问,不要暴露到公网。
|
||||
- 两台机器必须使用 NTP/chrony 同步时间;端到端延迟依赖两边时钟一致。
|
||||
|
||||
## 统计口径
|
||||
|
||||
- 发送成功以 `{ctrl code=2xx, params.seq>0}` 为准,形成两台机器共享的 ACK 台账。
|
||||
@@ -10,12 +48,19 @@
|
||||
- 实时 drain 结束后通过 `{get what=data}` 按 ACK 的 Topic/Seq 回查历史,区分跨 Pod 实时漏投与数据库持久化缺失。
|
||||
- `manifest.json` 含登录 token,文件权限为 `0600`,不得提交到 Git 或放入结果包。
|
||||
|
||||
## 构建与配置
|
||||
## 两台机器初始化
|
||||
|
||||
两台机器使用同一版本二进制、配置和 manifest:
|
||||
两台机器先检出完全相同的 Git 提交,并分别构建本机二进制:
|
||||
|
||||
```bash
|
||||
git rev-parse HEAD
|
||||
go build -o loadtest/im-pressure/im-pressure ./loadtest/im-pressure
|
||||
ulimit -n 100000
|
||||
```
|
||||
|
||||
只在机器 A 创建配置:
|
||||
|
||||
```bash
|
||||
cp loadtest/im-pressure/config.example.json loadtest/im-pressure/config.json
|
||||
export IM_API_KEY='...'
|
||||
export IM_LOAD_PASSWORD='...'
|
||||
@@ -23,9 +68,13 @@ export IM_LOAD_PASSWORD='...'
|
||||
|
||||
修改 `config.json`:`http_base` 指向 IM HTTP API;`endpoints.a/b` 分别填写两台机器应直连的 WS Pod/LB 地址,多个地址时用户会轮询分配。正式测试保持 `insecure_tls=false`。
|
||||
|
||||
## 一次性准备
|
||||
`endpoints.a` 是机器 A 的 1000 个用户使用的 WS Pod/LB 地址,`endpoints.b` 是机器 B 的 1000 个用户使用的地址。要验证跨 Pod 投递时,应让 A、B 连接到不同 Pod 或不同的定向入口;如果都填同一个普通 LB,连接落在哪个 Pod 将由 LB 决定。
|
||||
|
||||
只在一台机器执行。命令可重复运行,会复用已有账号、好友和群:
|
||||
机器 B 同样需要设置 `IM_API_KEY` 和 `IM_LOAD_PASSWORD`。密码用于 Token 失效时自动回退 Basic 登录,不能只在机器 A 设置。
|
||||
|
||||
## 机器 A:一次性准备
|
||||
|
||||
以下命令只在当前机器 A 执行。命令可重复运行,会复用已有账号、好友和群:
|
||||
|
||||
```bash
|
||||
./loadtest/im-pressure/im-pressure prepare \
|
||||
@@ -37,87 +86,151 @@ export IM_LOAD_PASSWORD='...'
|
||||
-manifest loadtest/im-pressure/manifest.json
|
||||
```
|
||||
|
||||
将 `config.json` 和 `manifest.json` 安全复制到机器 B,并执行 `chmod 600 loadtest/im-pressure/manifest.json`。
|
||||
准备成功后,机器 A 的 manifest 中包含 2000 个账号 Token、1000 个 P2P Topic 和群 Topic。将配置和 manifest 安全复制到机器 B:
|
||||
|
||||
## 双机运行
|
||||
```bash
|
||||
export MACHINE_B_SSH='user@机器B内网IP'
|
||||
export MACHINE_B_REPO='/home/user/im_server'
|
||||
|
||||
先在机器 A 启动协调器。`run-id` 每轮必须唯一且不超过 24 个字符:
|
||||
scp loadtest/im-pressure/config.json \
|
||||
"${MACHINE_B_SSH}:${MACHINE_B_REPO}/loadtest/im-pressure/config.json"
|
||||
scp loadtest/im-pressure/manifest.json \
|
||||
"${MACHINE_B_SSH}:${MACHINE_B_REPO}/loadtest/im-pressure/manifest.json"
|
||||
```
|
||||
|
||||
机器 B 收到后执行:
|
||||
|
||||
```bash
|
||||
cd /home/user/im_server
|
||||
chmod 600 loadtest/im-pressure/manifest.json
|
||||
export IM_API_KEY='...'
|
||||
export IM_LOAD_PASSWORD='...'
|
||||
./loadtest/im-pressure/im-pressure verify \
|
||||
-config loadtest/im-pressure/config.json \
|
||||
-manifest loadtest/im-pressure/manifest.json
|
||||
```
|
||||
|
||||
`MACHINE_B_REPO` 必须填写机器 B 上仓库的绝对路径。每次机器 A 重新执行 `prepare` 并改变了 manifest,都必须重新同步到机器 B。
|
||||
|
||||
## 每轮双机运行
|
||||
|
||||
以下示例执行单聊场景。机器 A 设置本轮场景;两台机器使用同一个、每轮唯一且不超过 24 个字符的 `RUN_ID`,保证结果目录一致:
|
||||
|
||||
```bash
|
||||
export RUN_ID='p2p-20260927-01'
|
||||
export SCENARIO='p2p'
|
||||
export MACHINE_A_IP='机器A内网IP'
|
||||
export MACHINE_B_IP='机器B内网IP'
|
||||
mkdir -p "loadtest/im-pressure/results/${RUN_ID}"
|
||||
```
|
||||
|
||||
机器 A 应在正式起压前启动终端 A3 的指标采集,然后按 A1、A2、B1 的顺序启动协调器和两个 agent。
|
||||
|
||||
### 第一步:机器 A 启动协调器
|
||||
|
||||
机器 A 终端 A1:
|
||||
|
||||
```bash
|
||||
mkdir -p loadtest/im-pressure/results/p2p-001
|
||||
./loadtest/im-pressure/im-pressure coordinator \
|
||||
-listen :8090 -run-id p2p-001 -scenario p2p \
|
||||
-output loadtest/im-pressure/results/p2p-001/coordinator.json
|
||||
-listen :8090 \
|
||||
-run-id "${RUN_ID}" \
|
||||
-scenario "${SCENARIO}" \
|
||||
-output "loadtest/im-pressure/results/${RUN_ID}/coordinator.json"
|
||||
```
|
||||
|
||||
然后分别启动两个 agent。`COORDINATOR_IP` 必须是机器 B 可访问的机器 A 内网地址。
|
||||
协调器会等待两个 agent 都报告 1000 条连接 READY,再统一下发至少 30 秒后的开始时间。不要跳过协调器直接启动 agent。
|
||||
|
||||
机器 A:
|
||||
### 第二步:机器 A 启动 agent A
|
||||
|
||||
机器 A 终端 A2:
|
||||
|
||||
```bash
|
||||
./loadtest/im-pressure/im-pressure agent \
|
||||
-config loadtest/im-pressure/config.json \
|
||||
-manifest loadtest/im-pressure/manifest.json \
|
||||
-machine a -coordinator http://COORDINATOR_IP:8090 \
|
||||
-machine a \
|
||||
-coordinator "http://${MACHINE_A_IP}:8090" \
|
||||
-metrics-listen :9105 \
|
||||
-output loadtest/im-pressure/results/p2p-001/agent-a-summary.json
|
||||
-output "loadtest/im-pressure/results/${RUN_ID}/agent-a-summary.json"
|
||||
```
|
||||
|
||||
机器 B:
|
||||
### 第三步:机器 B 启动 agent B
|
||||
|
||||
机器 B 终端 B1 需要先设置与机器 A 相同的值:
|
||||
|
||||
```bash
|
||||
cd /home/user/im_server
|
||||
export IM_API_KEY='...'
|
||||
export IM_LOAD_PASSWORD='...'
|
||||
export RUN_ID='p2p-20260927-01'
|
||||
export MACHINE_A_IP='机器A内网IP'
|
||||
mkdir -p "loadtest/im-pressure/results/${RUN_ID}"
|
||||
|
||||
./loadtest/im-pressure/im-pressure agent \
|
||||
-config loadtest/im-pressure/config.json \
|
||||
-manifest loadtest/im-pressure/manifest.json \
|
||||
-machine b -coordinator http://COORDINATOR_IP:8090 \
|
||||
-machine b \
|
||||
-coordinator "http://${MACHINE_A_IP}:8090" \
|
||||
-metrics-listen :9105 \
|
||||
-output loadtest/im-pressure/results/p2p-001/agent-b-summary.json
|
||||
-output "loadtest/im-pressure/results/${RUN_ID}/agent-b-summary.json"
|
||||
```
|
||||
|
||||
机器 B 不需要传 `SCENARIO`,场景由机器 A 的 coordinator 下发。两个 agent 可以任意先后启动,但 coordinator 必须最先启动。
|
||||
|
||||
两个 agent 都建立 1000 条连接后,协调器下发统一的 UTC `start_at`。场景可替换为:
|
||||
|
||||
- `p2p`:1000 对用户两侧同时发送,默认每人 10 条、间隔 1 秒。
|
||||
- `group`:每台机器 500 个发送者,每人 2 条;全局每 100ms 一条,共 2000 条。
|
||||
- `mixed`:300 对私聊用户每人 5 条,同时每台 250 个群发送者各发 2 条。
|
||||
|
||||
## 合并报告
|
||||
## 机器 A:回收并合并报告
|
||||
|
||||
把两个 agent summary 放到同一台机器:
|
||||
两个 agent 完成历史回查并退出后,在机器 A 拉取机器 B 的 summary:
|
||||
|
||||
```bash
|
||||
scp "${MACHINE_B_SSH}:${MACHINE_B_REPO}/loadtest/im-pressure/results/${RUN_ID}/agent-b-summary.json" \
|
||||
"loadtest/im-pressure/results/${RUN_ID}/agent-b-summary.json"
|
||||
```
|
||||
|
||||
然后仍在机器 A 合并报告:
|
||||
|
||||
```bash
|
||||
./loadtest/im-pressure/im-pressure merge \
|
||||
-a loadtest/im-pressure/results/p2p-001/agent-a-summary.json \
|
||||
-b loadtest/im-pressure/results/p2p-001/agent-b-summary.json \
|
||||
-output loadtest/im-pressure/results/p2p-001/report.json
|
||||
-a "loadtest/im-pressure/results/${RUN_ID}/agent-a-summary.json" \
|
||||
-b "loadtest/im-pressure/results/${RUN_ID}/agent-b-summary.json" \
|
||||
-output "loadtest/im-pressure/results/${RUN_ID}/report.json"
|
||||
```
|
||||
|
||||
`report.json` 给出 ACK、实时投递、重复、乱序、断连和历史持久化核验结果。当前正确性门禁要求上述错误计数全部为 0。
|
||||
|
||||
每个 agent 在 `:9105/metrics` 暴露连接、发送、接收、重复、乱序、断连以及 Go/process 指标;端口冲突时可通过 `-metrics-listen` 修改,传空字符串可关闭。
|
||||
|
||||
## 指标采集
|
||||
## 机器 A:集中采集指标
|
||||
|
||||
`collect` 可并行抓取 Prometheus、Redis exporter、Kafka exporter、mysqld exporter、kube-state-metrics/cAdvisor 和压测机 node-exporter,原始响应按时间写入 JSONL:
|
||||
|
||||
```bash
|
||||
./loadtest/im-pressure/im-pressure collect \
|
||||
-duration 10m -interval 5s \
|
||||
-duration 20m -interval 5s \
|
||||
-url agent-a=http://127.0.0.1:9105/metrics \
|
||||
-url agent-b=http://${MACHINE_B_IP}:9105/metrics \
|
||||
-url im=http://PROMETHEUS_HOST/api/v1/query?query=up \
|
||||
-url redis=http://REDIS_EXPORTER/metrics \
|
||||
-url kafka=http://KAFKA_EXPORTER/metrics \
|
||||
-url mysql=http://MYSQLD_EXPORTER/metrics \
|
||||
-url node-a=http://NODE_A_EXPORTER/metrics \
|
||||
-url node-b=http://NODE_B_EXPORTER/metrics \
|
||||
-output loadtest/im-pressure/results/p2p-001/metrics.jsonl
|
||||
-output "loadtest/im-pressure/results/${RUN_ID}/metrics.jsonl"
|
||||
```
|
||||
|
||||
URL 含 `&` 时需用单引号包住整个 `name=url` 参数。建议起压前 2 分钟开始采集,结束后继续 5 分钟,以观察 Kafka lag、数据库落库追平时间及资源恢复。
|
||||
机器 A 终端 A3 运行采集器。URL 含 `&` 时需用单引号包住整个 `name=url` 参数。建议起压前 2 分钟开始采集,结束后继续 5 分钟,以观察 Kafka lag、数据库落库追平时间及资源恢复。如果机器 A 无法访问机器 B 的 `9105`,就在机器 B 单独运行一份 `collect`,结束后把 JSONL 一并传回机器 A。
|
||||
|
||||
## 运行前检查
|
||||
|
||||
```bash
|
||||
ulimit -n 100000
|
||||
curl -fsS http://COORDINATOR_IP:8090/v1/status
|
||||
curl -fsS "http://${MACHINE_A_IP}:8090/v1/status"
|
||||
curl -fsS http://127.0.0.1:9105/metrics | head
|
||||
```
|
||||
|
||||
两台压测机应完成时钟同步,并确认压测出口、Ingress、Pod 与 Redis/MySQL/Kafka 连接数限制可以容纳本轮负载。协调器没有鉴权,只能监听在受控压测网络中。
|
||||
|
||||
Reference in New Issue
Block a user