- 即时通讯
- 后端
【免费下载链接】WuKongIM
More than just IM 不只是即时通讯(IM)
导读
本文基于 WuKongIM 仓库内的《真实网络权限读取并行验证》报告(docs/reports/2026-09-27-send-ban-parallel-rpc.md),完整讲解如何在正常生产二进制上、通过五节点黑盒 E2E 证明"一个 SEND 请求的两个远端权限信封存在执行重叠",并验证 quorum 丢失时的失败关闭与恢复后无错误提交。读者将掌握:节点聚合权限 RPC 的设计动机、用公开指标(inflight 与 direct admission 计数)而非内部日志证明并行性的方法、受控 quorum 故障注入的完整流程,以及该验证在整个 send ban 验收矩阵(R3)中的精确边界。
为什么需要"真实网络"验证并行性
在 WuKongIM 的用户/频道发送禁令设计中(见 docs/specs/user-channel-send-ban.md 第 7 节),权限事实规划会把一条 SEND 涉及的发送者用户事实与目标频道事实统一去重,再按"目标 Leader 节点"聚合:同一个远端节点上的多个 Slot 子请求被装进一个节点信封(node envelope),不同远端节点之间的信封则并行执行。
这个设计的核心收益在规格书中有明确的 RPC 成本公式:
| 方案 | 权限业务查询的跨节点 RPC 数 | 关键性质 |
|---|---|---|
| 对每条消息逐项查询 | 随消息数 × 事实数增长 | 串行轮次多,不采用 |
| 当前批量路径 | 约 S_remote 次 | 同节点不同 Slot 仍分别调用 |
| 节点聚合方案 | R 次(超过字节/条目上限按节点分块增加) | 同节点多个 Slot 共用一个传输信封 |
例如一个批次涉及 20 个 Slot,其 Leader 都落在两个远端节点:当前实现通常要发 20 个权限查询 RPC,而节点聚合方案只需 2 个节点批量 RPC。
但"设计上并行"不等于"实际上并行"。此前 R3 的证据主要来自隔离层验证(TestSendPermissionRPCBoundaries一类受控适配器测试),它们能精确拦住屏障、篡改线上同格式响应,却无法证明真实网络、真实 Raft 调度下的行为。因此本报告的任务就是:在正常生产二进制上,用黑盒观测证明两个远端权限信封真实存在执行重叠。
验证场景设计:两个策略 Slot 分布在不同节点
报告的验证场景刻意构造了一个"两组之外有接入节点"的五节点拓扑,让一次 SEND 同时触及两个远端 Slot 的权威读取:
| 角色 | 位置 |
|---|---|
| 用户策略(Slot 1) | Leader 为节点 4,另一 voter 为节点 5 |
| 频道策略(Slot 2) | Leader 为节点 3,另一 voter 为节点 1 |
| 接入节点 | 节点 2(两组之外的接入节点) |
| 故障注入 | 停止节点 5 和节点 1 |
集群保持 256 Hash Slots、12 个物理 Slots、每个 Slot 两个 voter,这与 E2E 测试中WK_CLUSTER_HASH_SLOT_COUNT=256、WK_CLUSTER_INITIAL_SLOT_COUNT=12的配置一致(见 test/e2e/message/send_ban/send_ban_test.go)。通过公开 Manager 的实际状态确认 placement,而不是假设路由。
停止节点 5 和节点 1 后,两个策略的 Leader(节点 4、节点 3)以及接入节点(节点 2)仍然运行。这是受控 quorum 故障——每个 Slot 恰好损失一个 voter,各自仍保有 Leader 与一个 voter,因此不构成双副本高可用性证明,也不属于完全失联的降级场景。
黑盒证明方法:inflight 加 direct admission 计数
要证明"并行",关键在于排除"前一个信封结束后由另一个信封替换"的假象。报告采用的方法是:只发起一个不做应用重试的 HTTP SEND,然后通过公开指标依次观察:
- 节点 4 的权限读取 inflight 为 1;
- 节点 3 的权限读取 inflight 为 1;
- 节点 4 的权限读取 inflight 再次为 1(仍在执行中)。
三次采集开始时间为03:29:44.295287、03:29:44.308896、03:29:44.316620(UTC)。节点 4 的两次正值因此属于同一个持续执行的信封,中间被节点 3 的正值观察覆盖——这正是两个远端信封执行重叠的直接证据。
随后通过独立的后续采集确认:两位 Leader 的 direct admission 计数都只增加一次。这一步很关键:它证明节点 4 的两次 inflight 正值不是"前一个信封结束后被另一个替换",因为如果发生了替换,admission 计数会相应增加。整个证明不依赖可能被缓冲的 transport RPC 完成计数。
同时需要诚实说明:三次采集时间点是客户端采集边界,不是精确的服务端请求起止时间,因此不能据此推导最小重叠时长或吞吐提升比例——这体现了报告对证据边界的严谨态度。
失败关闭与无副作用验证
在 quorum 故障窗口内:
- 正常成功对照与故障观察窗口的远端信封增量均为2(两个远端节点各一个信封);
- 失败请求在约2062ms后返回HTTP 503,没有返回消息 ID 或序号;
- 两个 owner(用户策略 Slot 与频道策略 Slot)的 inflight 最终归零,没有泄漏的执行许可或残留读者。
恢复两个 voter、等待公开 readiness 和实际 Slot Leader 稳定后,发送恢复对照。最终完整历史恰好为 warm、control、recovered 三条,没有parallel-denied条目——这证明拒绝请求没有产生任何新的持久化记录或投递,即"拒绝无副作用"。
这一黑盒行为与源码中的错误映射逻辑吻合:ReadSendPermissionMetadataBatch在两次路由尝试后仍失败会把结果标为ErrReadStaleRoute或ErrPermissionBusy(见 pkg/slot/proxy/send_permission_rpc.go),而服务端在 quorum 不可用时返回 503,这正是 docs/specs/user-channel-send-ban.md 第 5 节规定的503 temporarily_unavailable语义。
构建严谨性:两轮运行与二进制溯源
报告在"构建与限制"一节记录了验证的严谨流程:
- 首轮:命令遗漏了二进制覆盖和报告环境参数,夹具自动构建了 e2e-tagged 产品,该轮44.98 秒通过。报告明确保留它的原始日志、报告与实际二进制摘要,不将其伪称为正常生产构建证据——因为 e2e-tagged 产物不等于正常产品二进制。
- 末轮:明确指定从
dd3ea4495提交构建的正常产品二进制,并写入指定 artifact 路径,完整重跑通过(36.96 秒)。
两轮结果、失败场景计划、冻结上下文、源文件与二进制摘要、精确重跑命令全部保存在docs/reports/assets/send-ban-parallel-rpc-20260927/manifest.json(注:该目录在 assets 下按报告组织,与其它报告产物一致)。这种"保留失败、不伪称、给出可复现命令"的做法,是 WuKongIM 验收报告的一贯准则。
该验证在验收矩阵中的精确边界
本报告是 send ban 完整验收核对(docs/reports/2026-09-24-send-ban-acceptance-audit.md)中R3(placement 与节点聚合)的补充证据。它的贡献与限制必须成对理解:
贡献:补齐了 R3 的真实网络并行存在性,以及两个远端节点各一个权限信封的计数证据。此前 R3 只有"同远端节点两个 Slot 为 1 个 RPC/2 次 Slot 读取"的计数验证,没有真实网络下的执行重叠证明。
明确不成立的部分:
- 五目标节点、最多四个 worker 的最大并发限制仍由既有隔离 gate 验证(
TestSendPermissionRPCBoundaries等 integration 测试); - 此测试没有证明绝对性能,三次采集边界不能推导吞吐提升比例;
- 此测试没有使 R2 持续资格(5000 频道/4500 SEND/s/30 分钟)或 R6 的 5% 对照门槛变为通过——验收矩阵中这些项目仍明确标记为未验证。
源码级印证:节点聚合 RPC 的实现骨架
报告描述的黑盒行为,在 pkg/slot/proxy/send_permission_rpc.go 中可以找到完整实现对应:
- 节点信封聚合:
ReadSendPermissionMetadataBatch先按路由 fence(SendPermissionFence:SlotID、LeaderNodeID、LeaderTerm、ConfigEpoch、RouteRevision)分组,再按 LeaderNodeID 排序并打包成sendPermissionRequest,每个信封携带多个 Slot 子组(sendPermissionGroup)。请求/响应各限 1 MiB(sendPermissionMaxBytes)。 - 本地短路:
callSendPermission中若 Leader 是本机,直接调用serveSendPermissions,无 loopback RPC;本机仅是 follower/非副本时才走远程 RPCService。 - fresh barrier:
readSendPermissionSlot对每个 Slot 子批次先执行ReadSlotBarrier(fresh safe ReadIndex 并等待 durable apply),再读只读数据库 snapshot,返回前重新校验 authority fence 与 Hash Slot 映射,变化则返回stale_route,不输出旧成功。 - 有界准入:
acquireSendPermissionEnvelope限制最多 64 个信封在执行、最多 1024 个等待、等待未解码字节合计不超过 16 MiB、等待上限 2 秒;满载/等待超限返回ErrPermissionBusy(wire 上为{"format":1,"error":"busy","groups":[]})。这一容量来自 2026-09-30 的 500 SEND/s CI 观察:16 个独立信封在 ReadIndex 约 30ms 往返时执行预算不足,调整执行上限为 64 后全部完成。 - 可观测性:
SendPermissionObserver接口(pkg/slot/proxy/send_permission_observer.go)上报计数(node_envelopes、local_envelopes、request_bytes、slot_groups等)与阶段耗时(admission、route、barrier、snapshot、rpc),其中 barrier 单列,避免 RPC 聚合掩盖 quorum 成本——这正是本报告读取"inflight 与 direct admission 计数"的公开指标来源。
配套测试同样印证了报告证据链:
- pkg/slot/proxy/send_permission_rpc_test.go 的
TestSendPermissionNodeBatchAndFreshBarriers验证两个远端信封合并、每个信封内两个 Slot 各走一次 fresh barrier; - pkg/slot/proxy/send_permission_boundaries_integration_test.go 的
TestSendPermissionRPCBoundaries验证 4096 事实分块、1 MiB 精确边界、四 worker、16 许可饱和与取消复用——但报告明确声明隔离验证不能替代真实网络时序证明; - pkg/slot/proxy/send_permission_capacity_integration_test.go 的
TestSendPermissionBurstWithSlowFreshBarriers复现"慢 fresh barrier 下独立调用方排队"并验证每个调用方都获得自己的 barrier。
结论与可复现要点
《真实网络权限读取并行验证》以 36.96 秒的五节点黑盒 E2E,完成了 R3 的关键一步:在未修改生产实现的前提下,用公开指标证明一个 SEND 的两个远端权限信封存在真实执行重叠,并验证了 quorum 丢失时的失败关闭(HTTP 503、无消息 ID/序号、inflight 归零)与恢复后的无错误提交(完整历史恰好三条,无parallel-denied)。
复现与引用本验证时请记住三条边界:构建必须使用指定提交(dd3ea4495)的正常产品二进制;采集时间点是客户端边界,不可推导最小重叠时长;该结果不构成性能资格,R2 持续资格与 R6 的 5% 对照门槛仍保持未验证状态。
- 即时通讯
- 后端
【免费下载链接】WuKongIM
More than just IM 不只是即时通讯(IM)
相关推荐
WuKongIM 发送权限 RPC 边界验证:用可控集群端口证明 4096 事实聚合、1 MiB 信封与节点级准入
WuKongIM 发送权限 RPC 边界验证:用可控集群端口证明 4096 事实聚合、1 MiB 信封与节点级准入 本篇基于 WuKongIM 仓库中 Send
即时通讯后端WuKongIM 发送准入诊断:权限指标证据补齐契约与三节点重跑验证解析
WuKongIM 发送准入诊断:权限指标证据补齐契约与三节点重跑验证解析 本文基于 WuKongIM 仓库中的压力诊断记录 docs/reports/2026
即时通讯后端WuKongIM 禁发与 Quorum 拒绝的无投递验证:真实三节点 E2E 投递边界证明
WuKongIM 禁发与 Quorum 拒绝的无投递验证:真实三节点 E2E 投递边界证明 本文基于 WuKongIM 仓库中的真实 E2E 测试报告 2026
即时通讯后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考