5.1 KiB
5.1 KiB
IM 多开跨 Pod 实时投递压测方案
日期:2026-09-13
006 商户、2000 账号、两台压测机的可执行场景与统计口径见 IM-006商户双机消息压力测试方案。本文保留为通用阶梯与指标说明。
1. 目标
验证 IM Server 使用 Redis realtime fanout 后,在多 Pod、多端登录、群消息和群业务事件场景下的实时投递能力。
本次压测重点观察:
- 跨 Pod 在线消息是否能投递到所有目标 WS 连接。
- 群消息在多 Pod 下的端到端延迟。
- Redis Pub/Sub 发布、接收、投递失败和本地无连接的比例。
- Hub 队列满、WS 写队列满、Redis 发布失败等异常是否可观测。
- Pod 扩缩容、单 Pod 重启时是否出现明显丢消息或延迟尖刺。
2. 前置环境
建议至少准备:
- IM Server:3 个 Pod。
- Redis:独立实例或 Redis Cluster,开启
group_fanout_enabled。 - MySQL:使用压测租户库。
- 监控:开启
/metrics,采集 Prometheus 指标。 - 账号:准备足够多的群成员账号 CSV,格式为
username,password[,token]。 - 群 topic:提前创建一个大群,并把压测账号加入该群。
每个 Pod 必须配置不同的节点标识:
"node_id": "im-pod-1"
或通过环境变量:
IM_NODE_ID=im-pod-1
3. 新增服务端指标
本次改造新增 Prometheus 指标:
realtime_fanout_events_total{stage,kind,target_type,status}
realtime_fanout_delivery_duration_seconds_bucket{kind,target_type}
常用查询:
sum by (stage, kind, target_type, status) (rate(realtime_fanout_events_total[1m]))
histogram_quantile(
0.95,
sum by (le, kind, target_type) (rate(realtime_fanout_delivery_duration_seconds_bucket[5m]))
)
重点关注 status:
publish/ok:本 Pod 成功发布到 Redis。publish/error:Redis 发布失败。publish/skip_native_cluster:启用了 Tinode 原生 cluster,跳过 Redis topic fanout。receive/ok:其他 Pod 收到 Redis fanout。receive/malformed:收到无法解析的消息。deliver/local_delivered:本 Pod 找到本地 WS 并投递。deliver/no_local_session:本 Pod 没有目标本地连接,属于正常情况。deliver/hub_full:Hub routeSrv 队列满,需要重点告警。deliver/skip_no_session_store:session store 未初始化。
4. 压测脚本
脚本位置:
loadtest/realtime_fanout_probe.go
运行示例:
go run ./loadtest/realtime_fanout_probe.go \
-ws "ws://im-pod-1.example.com/v0/channels,ws://im-pod-2.example.com/v0/channels,ws://im-pod-3.example.com/v0/channels" \
-apikey "$IM_API_KEY" \
-accounts loadtest/users.csv \
-topic grpXXXXXXXXXXXX \
-subscribers 3000 \
-publishers 10 \
-rate 200 \
-duration 10m \
-ramp 2m
脚本行为:
- 按 CSV 账号建立 WS 连接。
- 将连接均匀分布到
-ws提供的多个 Pod 地址。 - 每个连接登录并订阅同一个群 topic。
- 从前
-publishers个连接中选择发布者。 - 按
-rate总速率发布带probe_id和sent_at_unix_nano的群消息。 - 所有订阅连接统计收到的
{data},输出接收数、丢失率、p50/p95/p99/max 延迟。
输出示例:
==== realtime fanout probe summary ====
published=120000 active_subscribers=3000 expected_deliveries=360000000 received=359998200 lost=1800 loss_rate=0.0005% unique_messages_seen=120000 errors=0 ctrl_acks=120000
latency p50=18ms p95=65ms p99=140ms max=900ms samples=359998200
5. 压测阶梯
建议按下面阶梯逐步推进,每个阶梯至少跑 10 分钟:
| 阶段 | Pod | 在线连接 | 发布者 | 总 QPS | 目标 |
|---|---|---|---|---|---|
| S1 | 3 | 300 | 1 | 10 | 验证链路正确性 |
| S2 | 3 | 3000 | 10 | 100 | 验证常规群聊压力 |
| S3 | 3 | 10000 | 20 | 300 | 验证大群在线 fanout |
| S4 | 6 | 30000 | 50 | 500 | 验证扩容后的 Redis fanout |
| S5 | 6 | 30000 | 50 | 1000 | 探测上限和队列瓶颈 |
6. 通过标准
建议初始通过标准:
publish/error为 0。receive/malformed为 0。deliver/hub_full为 0。- 压测脚本统计丢失率低于 0.01%。
- p95 端到端延迟低于 200ms。
- p99 端到端延迟低于 500ms。
- Pod CPU、内存、GC 无持续上升趋势。
- Redis CPU 不超过 70%,网络出入带宽有余量。
7. 故障注入
基础压测通过后执行:
- 压测中重启一个 IM Pod,观察其他 Pod 是否继续投递。
- 压测中扩容 Pod 数,观察
receive/ok是否按 Pod 数增加。 - 临时降低 Hub/WS 队列容量或制造慢客户端,确认
hub_full、WS 写失败日志可见。 - Redis 短暂不可用,确认
publish/error增加,恢复后新消息继续投递。
8. 结果记录
每轮记录:
- Git commit。
- IM Pod 数量和规格。
- Redis 规格。
- 在线连接数、发布 QPS、消息大小。
- 脚本输出摘要。
- Prometheus p95/p99。
publish/error、deliver/hub_full、WS 写失败数量。- Pod 重启/扩容期间的最大延迟和丢失率。