优先级验证:已知用户禁令先于频道 Slot 故障裁决)
即时通讯后端【免费下载链接】WuKongIMMore than just IM 不只是即时通讯(IM)项目地址https://gitcode.com/gh_mirrors/wu/WuKongIM点击查看免费下载导读本文基于 WuKongIM 仓库中的 E2E 验证报告 docs/reports/2026-09-24-send-ban-priority.md完整还原一次真实的进程级故障优先级验证当目标频道的权威 Slot 宕机、策略查询返回 503 时已经写入的用户发送禁令UID Send Ban依然可以独立裁决并拒绝发送。读者将掌握 WuKongIM 发送禁令的优先级判定顺序、三节点集群下如何人为构造一个策略可用、另一个策略不可用的确定性场景以及如何用一条 Go E2E 命令复现该验证并产出 JSON 证据报告。验证背景设计 F7 与发送禁令裁决WuKongIM 在消息发送路径上引入了**发送禁令send_ban**机制用于按用户UID或按目标频道Channel粒度的发送控制。消息在真正落库之前必须经过权限裁决裁决结论直接影响协议层返回的原因码。本次验证对应设计 F7证明用户禁令与频道 Slot 不可用两类故障同时存在时系统按既定优先级裁决——已知的用户禁令先于频道策略的可用性判定即使频道策略权威节点宕机被禁用户的消息仍然被拒绝而不是放行或错误重试。从源码看这一优先级并非测试临时设计而是发送权限链路的固有顺序。internal/usecase/message/FLOW.md 明确写道UID SendBan and actual source-Channel SendBan/Disband precede all system identity, system-device and plugin exemptions——即 UID 禁令与源频道禁令排在所有系统身份、系统设备和插件豁免之前。测试拓扑与确定性故障构造集群参数验证在三节点集群上进行关键配置通过节点环境变量覆盖对应 send_ban_test.go 中的suite.WithNodeConfigOverrides配置项取值说明WK_CLUSTER_HASH_SLOT_COUNT256全集群共 256 个 Hash SlotWK_CLUSTER_INITIAL_SLOT_COUNT12初始创建 12 个物理 SlotWK_CLUSTER_SLOT_REPLICA_N1每个 Slot 仅 1 个 voter单副本WK_GATEWAY_TOKEN_AUTH_ONfalse关闭 token 认证专注权限裁决路径WK_MESSAGE_PERMISSION_CACHE_TTL1h消息权限缓存 TTL 为 1 小时选择单副本1 voter/Slot是为了确定性制造一个策略 Slot 不可用而另一个仍可用的场景正如报告明确声明不是高可用部署的推荐或承诺。读者切勿将本拓扑理解为生产高可用配置。Slot 放置与接入节点通过公开的 Manager placement 接口确认UID 的用户策略 Slot 12 位于节点 3UID 为ban-priority-sender由crc32.ChecksumIEEE(uid) % 256计算落槽频道的策略 Slot 8 位于节点 1节点 2 为第三方接入节点ingressID既非 UID 权威也非频道权威。测试先用ban-priority-room-N逐一尝试找到与用户 Slot 权威不同 Leader 的频道房间从而把用户策略权威与频道策略权威物理拆开到不同节点见 send_ban_test.go。故障注入顺序先成功发送priority-warm预热证明基线链路可用写入用户禁令send_ban1停止频道策略权威所在的节点 1通过公开频道策略查询GET /channel/send_ban探测返回HTTP 503证明目标策略权威确实不可用测试中显式断言http.StatusServiceUnavailable见 send_ban_test.go。操作矩阵完整结果断言报告给出了四步操作矩阵是本次验证的核心证据完整继承如下操作接入节点结果用户禁令仍为 1UID owner 与第三节点HTTP 200、SEND 原因码 25无消息 ID/序号写入用户禁令 0UID owner 与第三节点HTTP 503无消息 ID/序号再写入用户禁令 1第三节点原因码 25无消息 ID/序号恢复节点 1确认 Slot authority 稳定再解禁第三节点priority-recovered成功几个关键语义点原因码 25即协议层ReasonSendBan用户或目标频道禁止发送定义于 pkg/protocol/frame/common.go按ReasonCode枚举顺序ReasonUnknown0、ReasonSuccess1…… 依次递增到ReasonSendBan25被拒绝的请求返回时无消息 ID 也无消息序号MessageID0、MessageSeq0测试断言require.Zero拒绝请求的消息 ID/序号send_ban_test.go所有拒绝请求仅执行一次不重试直到放行——这是测试纪律的核心约束AGENTS.md 中同样强调Never retry a ban rejection until it succeeds见 test/e2e/message/send_ban/AGENTS.md禁令写入版本依次为 1–4策略切换后的请求立即按新策略执行无需等待缓存过期或额外刷新。源码纵深优先级是如何实现的用户禁令先于频道策略在 internal/usecase/message/permission.go 的权限入口中消息发送前按频道类型分派检查其中单人会话person会先执行checkTerminalChannelPermission再执行checkPersonSendPermission。真正体现用户禁令优先的是底层裁决顺序checkSenderSendPermissionpermission.go调用GetUserSendPolicy(ctx, fromUID)读取 UID 策略若SendBan ! 0则调用observeSendBan(user, 1)并直接返回ReasonSendBancheckTerminalChannelPermissionpermission.go读取频道策略先判Disband解散再判SendBan命中即返回ReasonSendBan。因此当用户已被禁SendBan1时发送请求在任何需要查询频道权威的环节之前就已命中用户策略并返回原因码 25——这正是频道 Slot 宕机返回 503用户禁令仍能裁决拒绝的实现基础被禁用户不需要依赖频道权威可用。HTTP 层面对不可用的表达/user/send_ban与/channel/send_ban的读写路由注册于 internal/access/api/send_ban.go。当底层 usecase 不可用或查询失败时writeSendBanResult统一将错误映射为HTTP 503 temporarily_unavailablesend_ban.go。测试正是利用这一点写入解禁send_ban0发生在频道权威宕机期间因此返回 503——解禁写入本身也受 Slot 权威可用性约束而读取用户禁令不受影响。公开同步契约验证零副作用验证最后通过成员公开接口POST /channel/messagesync核对完整历史返回more0无更多分页且严格等于两个成功请求priority-warm与恢复后的priority-recovered无任何拒绝记录或重复记录send_ban_test.go。这证明被 503 拒绝的解禁写入没有留下半成品记录被原因码 25 拒绝的发送没有产生任何持久化副作用。首次失败与独立发现Manager 历史查询不一致验证过程并非一帆风顺。首次运行耗时 33.85 秒失败于 Manager 完整历史查询而策略判定全部通过。第二次保留相同故障与判定改用成员公开同步契约核对历史同时记录三个节点的 Manager 响应节点 3、节点 2返回404 channel not found节点 1频道 Slot 权威返回两条完整记录成员同步从节点 2 同样返回两条完整记录。因此没有证据表明消息丢失。这是一个独立待查问题Manager 跨节点查询不一致已记录在 docs/development/CODE_QUALITY.md指向ManagementMessageReader.QueryMessages - ReadChannelCommitted权威路径且不能将其标记为已修复。原失败产物保留本次通过的是禁发优先级 公开成员历史断言二者边界分明。重跑命令与产物验证可一键复现完整命令Go 1.25.11 / Darwin arm64 实测通过WK_E2E_SEND_BAN_REPORT/tmp/send-ban-priority.json GOWORKoff go test -tagse2e ./test/e2e/message/send_ban -run ^TestKnownUserBanPrecedesUnavailableChannelSlot$ -count1 -timeout3m -p1 -v要点说明WK_E2E_SEND_BAN_REPORT指定报告输出路径测试结束时在指定路径写出.priority.json伴随文件若未设置默认写入系统临时目录下的wukongim-send-ban-report.json见 send_ban_test.go报告 JSON 包含节点数3、Hash Slot 数256、初始 Slot 数12、副本数1、源码修订号WK_E2E_SOURCE_REVISION、完整公开 Slot placementUID Slot 与频道 Slot、时间戳、**策略版本、SEND 决策状态码与原因码**与历史响应观测原报告还提及产物清单manifest.json与源码身份source.json两个伴随文件生产二进制与1ba4a6352相同本轮基于42b291b14仅补测试、无生产代码变更——这是一次纯验证性质的运行。边界与限制声明报告对验证范围保持了严格克制本文一并继承本项不是性能资格测试不改变原有的 30 分钟压测、三组重复对照以及其他故障验收缺口单副本拓扑不是高可用推荐选择 1 voter/Slot 仅为确定性构造故障不代表生产部署形态持久化侧零副作用的证明范围有限通过公开成员历史契约证明拒绝无副作用但报告明确表示*不扩展为所有在线投递矩阵的证明*Manager 跨节点查询不一致为独立未决问题禁止将本次验证通过解读为其已修复。总结本次验证用一次干净的三节点故障注入确认了 WuKongIM 发送禁令的一个关键优先级语义已知用户禁令send_ban1可以在目标频道策略权威完全不可用503时独立裁决并拒绝发送拒绝仅执行一次、不产生消息 ID/序号、不留下任何持久化副作用策略版本递增且切换后立即生效。结合 permission.go 的实现可见这是UID 策略先行这一设计原则在真实进程故障下的行为保证。对运维与二次开发者而言这份报告同时提供了可复现的 E2E 命令、明确的证据边界以及一个仍需跟进研究的 Manager 历史查询一致性问题。赞分享即时通讯后端【免费下载链接】WuKongIMMore than just IM 不只是即时通讯(IM)项目地址https://gitcode.com/gh_mirrors/wu/WuKongIM点击查看免费下载相关推荐WuKongIM 用户与频道发送禁令Send Ban完整验收审计功能矩阵、RPC 性能门槛与故障诊断实录WuKongIM 用户与频道发送禁令Send Ban完整验收审计功能矩阵、RPC 性能门槛与故障诊断实录 本文以 WuKongIM 发送禁令Send b即时通讯后端WuKongIM发送禁令在 Slot Leader 手动转移中保持生效的 E2E 验证实录WuKongIM发送禁令在 Slot Leader 手动转移中保持生效的 E2E 验证实录 本篇记录 WuKongIM 三节点进程级 E2E 如何验证“用户/即时通讯后端WuKongIM 发送禁令网关批次验证三节点黑盒 E2E 下 UID/频道分布与 ACK 逐条对齐WuKongIM 发送禁令网关批次验证三节点黑盒 E2E 下 UID/频道分布与 ACK 逐条对齐 本文基于 WuKongIM 仓库中的报告 send ban即时通讯后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考