- 即时通讯
- 后端
【免费下载链接】WuKongIM
More than just IM 不只是即时通讯(IM)
本文是一份面向 WuKongIM 内部 v2 动态数据节点 Stage 9 生产就绪验证的实操手册,核心场景是在真实 WKProto 流量持续运行的同时,通过 Manager 依次完成节点 4 的种子加入(seed join)、激活、Slot 上移(onboarding)、标记离开、网关排空(drain)、缩容迁移与安全移除,并全程采集状态与指标证据。读完本文,你将掌握wkcli sim压测命令的参数语义与运行机制、动态节点生命周期 8 步操作顺序、健康上报相关配置,以及如何用低基数指标验证“节点在 joining 阶段不可调度、激活且健康新鲜后才可调度”这一关键约束。
背景:这份手册要验证什么
这份可选人工冒烟手册是对test/e2e/cluster/dynamic_node_readiness自动化测试的补充。e2e 测试包在其 AGENTS.md 中明确了 Stage 9 的场景契约:启动一个静态三节点集群,在真实 WKProtoSEND -> SENDACK流量持续运行期间完成节点 4 的加入、激活、上移、缩容与移除,并用公开的 Manager HTTP 接口、公开的/metrics接口和 WKProto 客户端证明健康新鲜度与生命周期阻塞项全过程可解释。
冒烟手册与 e2e 测试共同遵守一条黑盒原则:只使用公开的 v2 bench、Manager、Metrics 和 WKProto 接口面,绝不导入服务端内部实现(不引用internal/app、internal/usecase、存储内部、Controller 内部或集群内部)。这让冒烟结果能真实反映生产可观察性,而不是依赖内部函数。
集群形态:健康上报参数怎么配
冒烟要求按接近生产的形态启动一个 Stage 9 集群:Manager HTTP、bench API、Metrics、网关监听器与健康上报设置全部开启。其中最关键的是节点健康上报的两个参数,通过环境变量注入:
WK_CLUSTER_NODE_HEALTH_REPORT_INTERVAL=5s WK_CLUSTER_NODE_HEALTH_REPORT_TTL=30s这两个变量在 internal/config/schema.go 中有明确的 TOML 路径映射,等价于wukongim.toml中[cluster]段的配置:
[cluster] node_health_report_interval = "5s" node_health_report_ttl = "30s"示例配置见仓库根目录 wukongim.toml.example。含义拆解:
node_health_report_interval:每个数据节点向集群上报一次健康状态的周期,默认5s。上报越频繁,健康新鲜度判定越敏感。node_health_report_ttl:一次健康上报被视为“新鲜”的有效期,默认30s。超过 TTL 未刷新,节点健康会被判定为stale(过期),从而触发调度与缩容阻塞。
在自动化 e2e 测试中,为了让验证时间可控,readinessOverrides()(见 test/e2e/cluster/dynamic_node_readiness/lifecycle_helpers_test.go)把上报间隔缩短到了500ms:
"WK_CLUSTER_NODE_HEALTH_REPORT_INTERVAL": "500ms", "WK_CLUSTER_NODE_HEALTH_REPORT_TTL": "30s",手册建议:本地短冒烟时,先把集群保持在 3 个活跃数据节点上,再通过种子加入引入节点 4,避免一开始就形成不完整的拓扑。
压测流量:wkcli sim 的参数与运行机制
在生命周期变更进行期间,通过公开的wkcli sim持续跑真实流量。手册给出的基准命令:
go run ./cmd/wkcli sim --server http://127.0.0.1:5001 --users 200 --groups 40 --group-members 20 --rate 2/s --status-listen 127.0.0.1:19091 --max-runtime 5m命令定义在 cmd/wkcli/internal/sim/command.go,参数默认值与校验逻辑在 cmd/wkcli/internal/sim/config.go。逐项解读:
| 参数 | 本冒烟取值 | 默认值 | 说明 |
|---|---|---|---|
--server | http://127.0.0.1:5001 | 必填(或--gateway/--context) | WuKongIM HTTP API 服务地址,可重复或逗号分隔传入多个 |
--users | 200 | 100 | 模拟用户数 |
--groups | 40 | 20 | 模拟群组频道数 |
--group-members | 20 | 10 | 每个群组的成员数 |
--rate | 2/s | 0.2/s | 每个群组的消息发送速率,格式如2/s |
--status-listen | 127.0.0.1:19091 | 127.0.0.1:19091 | 本地状态端点监听地址 |
--max-runtime | 5m | 0(不限时) | 模拟总运行时长上限,0 表示不限制 |
其余常用参数还包括:--gateway(WKProto TCP 网关地址,覆盖 preflight 探测到的网关)、--payload-size(默认128B,支持1KB、1MiB等)、--connect-rate(默认 20,每秒最大建连数)、--concurrency(默认 64,最大并发模拟操作数)、--ack-timeout(默认 5s,SENDACK 等待超时)、--heartbeat-interval(默认 30s,模拟客户端 PING 间隔)、--json(JSON 输出)。注意--rate是每个群组的速率,总发送速率 =rate × groups。
压测期间不要让 sim 结束:手册明确要求“Keep the simulator running while the operator performs the lifecycle flow”,因为通过标准的每一条都需要在流量不中断的前提下验证。
sim 内部如何工作
wkcli sim的运行时实现位于 cmd/wkcli/internal/sim/runtime.go,其执行脉络可以概括为:
- preflight:先向 bench API 探测目标能力并解析网关地址(runtime.go);
- setup:通过 v2 bench API 准备拓扑数据(用户、群组、成员);
- connect:按
--connect-rate限速批量建立 WKProto 客户端连接(frame.APP设备标记); - runTraffic:按总速率调度发送,每个模拟用户最多 32 条在途 SEND(
simClientMaxInflight),发送结果以ReasonSuccess计为messages_sent,失败或缺失 SENDACK 计为send_errors; - 重试:运行时状态机依次经历
starting → preflighting → setting_up → connecting → running → retrying → stopped,出错后以 2s 固定退避自动重连重跑(见 runtime.go),因此单次网络抖动不会终止整个冒烟。
sim 的实时快照通过本地状态端点暴露。状态服务器实现在 cmd/wkcli/internal/sim/server.go,提供两个 GET 端点:
/healthz:返回{"status":"ok"}的存活探针;/status:返回完整 JSON 快照(结构定义见 cmd/wkcli/internal/sim/status.go),字段包括state、run_id、target_servers、gateway_tcp_addrs、users、active_users、groups、group_members、messages_sent、send_errors、recv_messages、recv_dropped、reconnects、last_error、last_transition_at。
这正是手册“Evidence To Keep”中curl http://127.0.0.1:19091/status的数据来源:只要send_errors不持续增长、messages_sent持续增加,就说明生命周期操作期间流量一直在正常推进。
生命周期流程:8 步操作顺序
通过 Manager HTTP 接口或 Manager UI,按以下顺序执行(对应 e2e 测试 production_readiness_test.go 中逐步验证的同一流程):
- 种子加入节点 4:通过 seed join 把新节点接入现有 3 节点集群,JoinToken 校验通过后节点进入成员清单;
- 等待节点 4 进入
joining且健康alive新鲜:此时 Manager 能列出节点,健康上报保持新鲜,但节点不可调度——这是关键约束; - 激活节点 4:激活后等待 join state 变为
active,节点变为可调度; - 启动一个有界(bounded)Slot 上移任务到节点 4:把少量 Slot 副本迁往新节点,验证新增容量落地;
- 标记节点 4
leaving:进入缩容准备阶段; - 开启节点 4 的网关排空(gateway drain):停止新连接接入并排空存量连接;
- 推进一个有界的 Slot 缩容迁移,移离节点 4:把 Slot 数据迁往其他存活节点;
- 仅在
safe_to_remove=true后移除节点 4:最终移除前必须确认所有阻塞项已清空。
e2e 测试中对应的断言顺序值得参考:manager.EventuallyNodeJoinState(t, 4, "joining", ...)→eventuallyNodeSchedulable前的requireNodeNotSchedulable→ 激活后EventuallyNodeJoinState(..., "active")→ onboarding 计划与执行 →leaving→ 缩容排空 →EventuallyScaleInSafeToRemove→removed(见 production_readiness_test.go)。整个流程中每个阶段结束后都调用requireTrafficProgress确认发送仍在推进。
关于safe_to_remove的语义,可以在源码中找到精确定义:缩容目标“没有已知的 control、Slot、Channel 或 runtime 排空阻塞项”时才为真(见 internal/usecase/management/scale_in.go),并通过 Manager 诊断接口以 JSON 字段safe_to_remove暴露(见 internal/access/manager/dynamic_node_diagnostics.go)。
证据收集:要保留哪些数据
手册要求冒烟全程保留以下证据,供事后审计与复现:
curl http://127.0.0.1:19091/status:sim 运行快照,证明流量持续推进;- Manager 节点列表 JSON:每个生命周期转换前后各一份,对比 join state 与健康状态;
- Manager 缩容状态 JSON:最终移除前获取,确认
safe_to_remove; /metrics片段:重点采集以下 5 个指标。
这 5 个指标的完整定义与标签约束在 pkg/metrics/node_lifecycle.go 中实现:
| 指标 | 类型 | 标签 | 含义 |
|---|---|---|---|
wukongim_node_lifecycle_nodes | GaugeVec | join_state,status | 按持久化 join 状态与健康状态分组的当前节点数 |
wukongim_node_health_freshness_nodes | GaugeVec | freshness,status | 按健康新鲜度(fresh/stale/missing)与状态分组的节点数 |
wukongim_node_lifecycle_attempts_total | CounterVec | operation,result | 生命周期操作尝试次数(join/activate/mark_leaving/onboarding/scale_in等 ×ok/fail/conflict等) |
wukongim_node_scale_in_blockers_total | CounterVec | reason | 缩容阻塞原因计数(如target_health_missing、target_health_stale、target_runtime_not_ready等 9 种有界原因) |
wukongim_discovery_membership_revision | Gauge | 无 | 本地可见的成员版本号,用于确认成员变更已收敛 |
除此之外,同一文件还暴露了wukongim_node_health_report_age_seconds(健康上报最大年龄)、wukongim_node_onboarding_tasks(上移任务数)以及wukongim_slot_replica_move_*系列(Slot 副本迁移时长/失败/阶段观测),可用于更细粒度地审计上移与缩容迁移过程。
低基数设计是这套指标的核心原则:所有标签值都经过normalizeBoundedMetricLabel归一化(node_lifecycle.go),不在白名单内的值统一折叠为other/unknown。例如 join state 只允许active/joining/leaving/removed,健康状态只允许alive/suspect/down,操作只允许固定的 9 种。这避免了高基数标签拖垮 Prometheus,也让仪表盘聚合稳定可靠。e2e 测试的指标断言(metrics_helpers_test.go)会轮询直到目标标签组合出现,并校验最小值,例如wukongim_node_lifecycle_nodes{join_state="active",status="alive"} >= 3。
通过标准:如何判定冒烟成功
逐条对照手册的 Pass Criteria:
wkcli sim在 join、激活、上移、缩容与移除全程持续报告发送成功——用/status的messages_sent增量与send_errors收敛来判定;- 节点 4 仅在
joining时绝不可调度——通过 Manager 节点列表或调度相关状态确认; - 节点 4 仅在激活且健康
alive新鲜后才可调度——健康新鲜度需同时满足fresh == true、freshness == "fresh"、status == "alive"、RuntimeReady(见 lifecycle_helpers_test.go 的健康轮询条件); - 最终移除仅在 Slot、Channel、健康与网关排空阻塞项全部清空后才尝试——对应
safe_to_remove=true,并由wukongim_node_scale_in_blockers_total的各个 reason 标签给出可解释证据; - 指标以低基数标签暴露生命周期与健康证据——即上述全部指标均遵守有界标签白名单。
一键脚本与自动化对照
除了手工冒烟,仓库还提供了可直接运行的冒烟脚本 scripts/smoke-wkcli-sim-wukongim-three-nodes.sh,它启动本地三节点集群、跑一轮真实wkcli sim流量并采集证据。其中与动态节点生命周期相关的关键选项:
--auto-join-node:在 sim 发送阶段启动一个 seed join 数据节点(默认节点 4),配合--auto-join-after、--auto-join-seeds、--auto-join-token使用;--auto-promote-controller-voter:新节点就绪后通过 Manager API(POST /manager/nodes/{id}/activate、/controller-voter/promote)激活并提升为 Controller voter;--fault-kill-node:在发送阶段杀掉一个静态节点,配合--fault-health-report-interval/--fault-health-report-ttl覆盖健康上报参数,用于故障演练对照。
自动化 e2e 版本可在仓库根目录按 AGENTS.md 的说明串行运行:
GOWORK=off go test -tags=e2e ./test/e2e/cluster/dynamic_node_readiness -count=1 -timeout 12m -p=1该包必须用-p=1串行执行,任务扇出保持有界(通常max_slot_moves=1),并优先轮询公开状态而不是固定 sleep,这些约束同样适用于手工冒烟:一次只做一个有界迁移,让证据链每一步都可解释。
小结
这份 Stage 9 冒烟手册的核心价值在于:用公开接口把“动态节点加入/缩容不影响在线业务”这一生产要求变成可重复、可取证、可观测的流程。实操要点可归纳为四件事:把健康上报间隔与 TTL 配成可观测的节奏(5s/30s,e2e 用 500ms 加速)、让wkcli sim流量贯穿全程并通过/status持续观察、严格按 8 步顺序执行生命周期操作并在每个转换点留证、最后用 5 个低基数指标(外加 Slot 迁移与上移任务系列)作为通过判据。如需深入底层实现,可继续阅读 pkg/metrics/node_lifecycle.go(指标与标签约束)、cmd/wkcli/internal/sim/runtime.go(sim 运行时与重试机制)、test/e2e/cluster/dynamic_node_readiness/production_readiness_test.go(完整生命周期断言)。
- 即时通讯
- 后端
【免费下载链接】WuKongIM
More than just IM 不只是即时通讯(IM)
相关推荐
WuKongIM 动态节点缩容收尾:Stage 5E 黑盒 e2e 冒烟验证 removed 墓碑路径
WuKongIM 动态节点缩容收尾:Stage 5E 黑盒 e2e 冒烟验证 removed 墓碑路径 本篇基于 WuKongIM 仓库中的动态节点生命周期实施
即时通讯后端WuKongIM 动态数据节点加入与激活:Stage 2 以 ControllerV2 为唯一持久成员源的生命周期写入路径
WuKongIM 动态数据节点加入与激活:Stage 2 以 ControllerV2 为唯一持久成员源的生命周期写入路径 本文围绕 WuKongIM 的 in
即时通讯后端WuKongIM 动态节点生命周期 Stage 4:MarkNodeLeaving、Fail-Closed 安全报告与有界 Slot 缩容排空实战
WuKongIM 动态节点生命周期 Stage 4:MarkNodeLeaving、Fail Closed 安全报告与有界 Slot 缩容排空实战 本篇基于 W
即时通讯后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考