送禁令(Send Ban)優(yōu)先級驗(yàn)證:已知用戶禁令先于頻道 Slot 故障裁決)
即時(shí)通訊后端【免費(fèi)下載鏈接】WuKongIMMore than just IM 不只是即時(shí)通訊(IM)項(xiàng)目地址https://gitcode.com/gh_mirrors/wu/WuKongIM點(diǎn)擊查看免費(fèi)下載導(dǎo)讀本文基于 WuKongIM 倉庫中的 E2E 驗(yàn)證報(bào)告 docs/reports/2026-09-24-send-ban-priority.md完整還原一次真實(shí)的進(jìn)程級故障優(yōu)先級驗(yàn)證當(dāng)目標(biāo)頻道的權(quán)威 Slot 宕機(jī)、策略查詢返回 503 時(shí)已經(jīng)寫入的用戶發(fā)送禁令UID Send Ban依然可以獨(dú)立裁決并拒絕發(fā)送。讀者將掌握 WuKongIM 發(fā)送禁令的優(yōu)先級判定順序、三節(jié)點(diǎn)集群下如何人為構(gòu)造一個(gè)策略可用、另一個(gè)策略不可用的確定性場景以及如何用一條 Go E2E 命令復(fù)現(xiàn)該驗(yàn)證并產(chǎn)出 JSON 證據(jù)報(bào)告。驗(yàn)證背景設(shè)計(jì) F7 與發(fā)送禁令裁決WuKongIM 在消息發(fā)送路徑上引入了**發(fā)送禁令send_ban**機(jī)制用于按用戶UID或按目標(biāo)頻道Channel粒度的發(fā)送控制。消息在真正落庫之前必須經(jīng)過權(quán)限裁決裁決結(jié)論直接影響協(xié)議層返回的原因碼。本次驗(yàn)證對應(yīng)設(shè)計(jì) F7證明用戶禁令與頻道 Slot 不可用兩類故障同時(shí)存在時(shí)系統(tǒng)按既定優(yōu)先級裁決——已知的用戶禁令先于頻道策略的可用性判定即使頻道策略權(quán)威節(jié)點(diǎn)宕機(jī)被禁用戶的消息仍然被拒絕而不是放行或錯誤重試。從源碼看這一優(yōu)先級并非測試臨時(shí)設(shè)計(jì)而是發(fā)送權(quán)限鏈路的固有順序。internal/usecase/message/FLOW.md 明確寫道UID SendBan and actual source-Channel SendBan/Disband precede all system identity, system-device and plugin exemptions——即 UID 禁令與源頻道禁令排在所有系統(tǒng)身份、系統(tǒng)設(shè)備和插件豁免之前。測試拓?fù)渑c確定性故障構(gòu)造集群參數(shù)驗(yàn)證在三節(jié)點(diǎn)集群上進(jìn)行關(guān)鍵配置通過節(jié)點(diǎn)環(huán)境變量覆蓋對應(yīng) send_ban_test.go 中的suite.WithNodeConfigOverrides配置項(xiàng)取值說明WK_CLUSTER_HASH_SLOT_COUNT256全集群共 256 個(gè) Hash SlotWK_CLUSTER_INITIAL_SLOT_COUNT12初始創(chuàng)建 12 個(gè)物理 SlotWK_CLUSTER_SLOT_REPLICA_N1每個(gè) Slot 僅 1 個(gè) voter單副本W(wǎng)K_GATEWAY_TOKEN_AUTH_ONfalse關(guān)閉 token 認(rèn)證專注權(quán)限裁決路徑WK_MESSAGE_PERMISSION_CACHE_TTL1h消息權(quán)限緩存 TTL 為 1 小時(shí)選擇單副本1 voter/Slot是為了確定性制造一個(gè)策略 Slot 不可用而另一個(gè)仍可用的場景正如報(bào)告明確聲明不是高可用部署的推薦或承諾。讀者切勿將本拓?fù)淅斫鉃樯a(chǎn)高可用配置。Slot 放置與接入節(jié)點(diǎn)通過公開的 Manager placement 接口確認(rèn)UID 的用戶策略 Slot 12 位于節(jié)點(diǎn) 3UID 為ban-priority-sender由crc32.ChecksumIEEE(uid) % 256計(jì)算落槽頻道的策略 Slot 8 位于節(jié)點(diǎn) 1節(jié)點(diǎn) 2 為第三方接入節(jié)點(diǎn)ingressID既非 UID 權(quán)威也非頻道權(quán)威。測試先用ban-priority-room-N逐一嘗試找到與用戶 Slot 權(quán)威不同 Leader 的頻道房間從而把用戶策略權(quán)威與頻道策略權(quán)威物理拆開到不同節(jié)點(diǎn)見 send_ban_test.go。故障注入順序先成功發(fā)送priority-warm預(yù)熱證明基線鏈路可用寫入用戶禁令send_ban1停止頻道策略權(quán)威所在的節(jié)點(diǎn) 1通過公開頻道策略查詢GET /channel/send_ban探測返回HTTP 503證明目標(biāo)策略權(quán)威確實(shí)不可用測試中顯式斷言http.StatusServiceUnavailable見 send_ban_test.go。操作矩陣完整結(jié)果斷言報(bào)告給出了四步操作矩陣是本次驗(yàn)證的核心證據(jù)完整繼承如下操作接入節(jié)點(diǎn)結(jié)果用戶禁令仍為 1UID owner 與第三節(jié)點(diǎn)HTTP 200、SEND 原因碼 25無消息 ID/序號寫入用戶禁令 0UID owner 與第三節(jié)點(diǎn)HTTP 503無消息 ID/序號再寫入用戶禁令 1第三節(jié)點(diǎn)原因碼 25無消息 ID/序號恢復(fù)節(jié)點(diǎn) 1確認(rèn) Slot authority 穩(wěn)定再解禁第三節(jié)點(diǎn)priority-recovered成功幾個(gè)關(guān)鍵語義點(diǎn)原因碼 25即協(xié)議層ReasonSendBan用戶或目標(biāo)頻道禁止發(fā)送定義于 pkg/protocol/frame/common.go按ReasonCode枚舉順序ReasonUnknown0、ReasonSuccess1…… 依次遞增到ReasonSendBan25被拒絕的請求返回時(shí)無消息 ID 也無消息序號MessageID0、MessageSeq0測試斷言require.Zero拒絕請求的消息 ID/序號send_ban_test.go所有拒絕請求僅執(zhí)行一次不重試直到放行——這是測試紀(jì)律的核心約束AGENTS.md 中同樣強(qiáng)調(diào)Never retry a ban rejection until it succeeds見 test/e2e/message/send_ban/AGENTS.md禁令寫入版本依次為 1–4策略切換后的請求立即按新策略執(zhí)行無需等待緩存過期或額外刷新。源碼縱深優(yōu)先級是如何實(shí)現(xiàn)的用戶禁令先于頻道策略在 internal/usecase/message/permission.go 的權(quán)限入口中消息發(fā)送前按頻道類型分派檢查其中單人會話person會先執(zhí)行checkTerminalChannelPermission再執(zhí)行checkPersonSendPermission。真正體現(xiàn)用戶禁令優(yōu)先的是底層裁決順序checkSenderSendPermissionpermission.go調(diào)用GetUserSendPolicy(ctx, fromUID)讀取 UID 策略若SendBan ! 0則調(diào)用observeSendBan(user, 1)并直接返回ReasonSendBancheckTerminalChannelPermissionpermission.go讀取頻道策略先判Disband解散再判SendBan命中即返回ReasonSendBan。因此當(dāng)用戶已被禁SendBan1時(shí)發(fā)送請求在任何需要查詢頻道權(quán)威的環(huán)節(jié)之前就已命中用戶策略并返回原因碼 25——這正是頻道 Slot 宕機(jī)返回 503用戶禁令仍能裁決拒絕的實(shí)現(xiàn)基礎(chǔ)被禁用戶不需要依賴頻道權(quán)威可用。HTTP 層面對不可用的表達(dá)/user/send_ban與/channel/send_ban的讀寫路由注冊于 internal/access/api/send_ban.go。當(dāng)?shù)讓?usecase 不可用或查詢失敗時(shí)writeSendBanResult統(tǒng)一將錯誤映射為HTTP 503 temporarily_unavailablesend_ban.go。測試正是利用這一點(diǎn)寫入解禁send_ban0發(fā)生在頻道權(quán)威宕機(jī)期間因此返回 503——解禁寫入本身也受 Slot 權(quán)威可用性約束而讀取用戶禁令不受影響。公開同步契約驗(yàn)證零副作用驗(yàn)證最后通過成員公開接口POST /channel/messagesync核對完整歷史返回more0無更多分頁且嚴(yán)格等于兩個(gè)成功請求priority-warm與恢復(fù)后的priority-recovered無任何拒絕記錄或重復(fù)記錄send_ban_test.go。這證明被 503 拒絕的解禁寫入沒有留下半成品記錄被原因碼 25 拒絕的發(fā)送沒有產(chǎn)生任何持久化副作用。首次失敗與獨(dú)立發(fā)現(xiàn)Manager 歷史查詢不一致驗(yàn)證過程并非一帆風(fēng)順。首次運(yùn)行耗時(shí) 33.85 秒失敗于 Manager 完整歷史查詢而策略判定全部通過。第二次保留相同故障與判定改用成員公開同步契約核對歷史同時(shí)記錄三個(gè)節(jié)點(diǎn)的 Manager 響應(yīng)節(jié)點(diǎn) 3、節(jié)點(diǎn) 2返回404 channel not found節(jié)點(diǎn) 1頻道 Slot 權(quán)威返回兩條完整記錄成員同步從節(jié)點(diǎn) 2 同樣返回兩條完整記錄。因此沒有證據(jù)表明消息丟失。這是一個(gè)獨(dú)立待查問題Manager 跨節(jié)點(diǎn)查詢不一致已記錄在 docs/development/CODE_QUALITY.md指向ManagementMessageReader.QueryMessages - ReadChannelCommitted權(quán)威路徑且不能將其標(biāo)記為已修復(fù)。原失敗產(chǎn)物保留本次通過的是禁發(fā)優(yōu)先級 公開成員歷史斷言二者邊界分明。重跑命令與產(chǎn)物驗(yàn)證可一鍵復(fù)現(xiàn)完整命令Go 1.25.11 / Darwin arm64 實(shí)測通過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要點(diǎn)說明WK_E2E_SEND_BAN_REPORT指定報(bào)告輸出路徑測試結(jié)束時(shí)在指定路徑寫出.priority.json伴隨文件若未設(shè)置默認(rèn)寫入系統(tǒng)臨時(shí)目錄下的wukongim-send-ban-report.json見 send_ban_test.go報(bào)告 JSON 包含節(jié)點(diǎn)數(shù)3、Hash Slot 數(shù)256、初始 Slot 數(shù)12、副本數(shù)1、源碼修訂號WK_E2E_SOURCE_REVISION、完整公開 Slot placementUID Slot 與頻道 Slot、時(shí)間戳、**策略版本、SEND 決策狀態(tài)碼與原因碼**與歷史響應(yīng)觀測原報(bào)告還提及產(chǎn)物清單manifest.json與源碼身份source.json兩個(gè)伴隨文件生產(chǎn)二進(jìn)制與1ba4a6352相同本輪基于42b291b14僅補(bǔ)測試、無生產(chǎn)代碼變更——這是一次純驗(yàn)證性質(zhì)的運(yùn)行。邊界與限制聲明報(bào)告對驗(yàn)證范圍保持了嚴(yán)格克制本文一并繼承本項(xiàng)不是性能資格測試不改變原有的 30 分鐘壓測、三組重復(fù)對照以及其他故障驗(yàn)收缺口單副本拓?fù)洳皇歉呖捎猛扑]選擇 1 voter/Slot 僅為確定性構(gòu)造故障不代表生產(chǎn)部署形態(tài)持久化側(cè)零副作用的證明范圍有限通過公開成員歷史契約證明拒絕無副作用但報(bào)告明確表示*不擴(kuò)展為所有在線投遞矩陣的證明*Manager 跨節(jié)點(diǎn)查詢不一致為獨(dú)立未決問題禁止將本次驗(yàn)證通過解讀為其已修復(fù)??偨Y(jié)本次驗(yàn)證用一次干凈的三節(jié)點(diǎn)故障注入確認(rèn)了 WuKongIM 發(fā)送禁令的一個(gè)關(guān)鍵優(yōu)先級語義已知用戶禁令send_ban1可以在目標(biāo)頻道策略權(quán)威完全不可用503時(shí)獨(dú)立裁決并拒絕發(fā)送拒絕僅執(zhí)行一次、不產(chǎn)生消息 ID/序號、不留下任何持久化副作用策略版本遞增且切換后立即生效。結(jié)合 permission.go 的實(shí)現(xiàn)可見這是UID 策略先行這一設(shè)計(jì)原則在真實(shí)進(jìn)程故障下的行為保證。對運(yùn)維與二次開發(fā)者而言這份報(bào)告同時(shí)提供了可復(fù)現(xiàn)的 E2E 命令、明確的證據(jù)邊界以及一個(gè)仍需跟進(jìn)研究的 Manager 歷史查詢一致性問題。贊分享即時(shí)通訊后端【免費(fèi)下載鏈接】WuKongIMMore than just IM 不只是即時(shí)通訊(IM)項(xiàng)目地址https://gitcode.com/gh_mirrors/wu/WuKongIM點(diǎn)擊查看免費(fèi)下載相關(guān)推薦WuKongIM 用戶與頻道發(fā)送禁令Send Ban完整驗(yàn)收審計(jì)功能矩陣、RPC 性能門檻與故障診斷實(shí)錄WuKongIM 用戶與頻道發(fā)送禁令Send Ban完整驗(yàn)收審計(jì)功能矩陣、RPC 性能門檻與故障診斷實(shí)錄 本文以 WuKongIM 發(fā)送禁令Send b即時(shí)通訊后端WuKongIM發(fā)送禁令在 Slot Leader 手動轉(zhuǎn)移中保持生效的 E2E 驗(yàn)證實(shí)錄WuKongIM發(fā)送禁令在 Slot Leader 手動轉(zhuǎn)移中保持生效的 E2E 驗(yàn)證實(shí)錄 本篇記錄 WuKongIM 三節(jié)點(diǎn)進(jìn)程級 E2E 如何驗(yàn)證“用戶/即時(shí)通訊后端WuKongIM 發(fā)送禁令網(wǎng)關(guān)批次驗(yàn)證三節(jié)點(diǎn)黑盒 E2E 下 UID/頻道分布與 ACK 逐條對齊WuKongIM 發(fā)送禁令網(wǎng)關(guān)批次驗(yàn)證三節(jié)點(diǎn)黑盒 E2E 下 UID/頻道分布與 ACK 逐條對齊 本文基于 WuKongIM 倉庫中的報(bào)告 send ban即時(shí)通訊后端創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考