Files
im_server/docs/IM-多开跨Pod实时投递压测方案.md
T

5.1 KiB
Raw Blame History

IM 多开跨 Pod 实时投递压测方案

日期:2026-09-13

006 商户、2000 账号、两台压测机的可执行场景与统计口径见 IM-006商户双机消息压力测试方案。本文保留为通用阶梯与指标说明。

1. 目标

验证 IM Server 使用 Redis realtime fanout 后,在多 Pod、多端登录、群消息和群业务事件场景下的实时投递能力。

本次压测重点观察:

  1. 跨 Pod 在线消息是否能投递到所有目标 WS 连接。
  2. 群消息在多 Pod 下的端到端延迟。
  3. Redis Pub/Sub 发布、接收、投递失败和本地无连接的比例。
  4. Hub 队列满、WS 写队列满、Redis 发布失败等异常是否可观测。
  5. 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

脚本行为:

  1. 按 CSV 账号建立 WS 连接。
  2. 将连接均匀分布到 -ws 提供的多个 Pod 地址。
  3. 每个连接登录并订阅同一个群 topic。
  4. 从前 -publishers 个连接中选择发布者。
  5. 按 -rate 总速率发布带 probe_id 和 sent_at_unix_nano 的群消息。
  6. 所有订阅连接统计收到的 {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. 故障注入

基础压测通过后执行:

  1. 压测中重启一个 IM Pod,观察其他 Pod 是否继续投递。
  2. 压测中扩容 Pod 数,观察 receive/ok 是否按 Pod 数增加。
  3. 临时降低 Hub/WS 队列容量或制造慢客户端,确认 hub_full、WS 写失败日志可见。
  4. Redis 短暂不可用,确认 publish/error 增加,恢复后新消息继续投递。

8. 结果记录

每轮记录:

  • Git commit。
  • IM Pod 数量和规格。
  • Redis 规格。
  • 在线连接数、发布 QPS、消息大小。
  • 脚本输出摘要。
  • Prometheus p95/p99。
  • publish/error、deliver/hub_full、WS 写失败数量。
  • Pod 重启/扩容期间的最大延迟和丢失率。