跳轉到

MatchRPG Server 生產就緒稽核:1M CCU 評分 82/100 與 JIT 盲點測試全流程

文檔資訊

  • 分類: architecture
  • 難度: advanced
  • 預估閱讀時間: 25 分鐘
  • 標籤: production-readiness, 1M-CCU, Go, PostgreSQL, Redis, concurrency, JIT-testing, architecture-audit, P0-findings, graceful-shutdown

摘要

針對 MatchRPG Server(Go + Twirp + pgxpool + Redis)進行完整生產就緒稽核,派遣 4 支並行 Agent 分別審查啟動路徑、資料庫寫入路徑、並發安全和架構合規,並額外執行 JIT 盲點測試。最終評分 82/100(Game Server 75/100、Publisher 80/100),發現 6 個 P0 阻斷問題和 12 個 P1 高優先問題。

關鍵學習

  • 1M CCU 的 DB 寫入估算:20K writes/s × 10 queries/op = 200K queries/s,超過單節點 PostgreSQL 上限 7-10x,需分片或讀寫分離

  • CAS 樂觀鎖重試最多 3x,EndBattle + ConsumeItems 嵌套 CAS 可達 9x 查詢放大,Worst Case 600K queries/s

  • 連接池預設值 DBMaxConns=30 嚴重不足,1M CCU 場景需要 100-150

  • Middleware 順序 P1 問題:Rate limiting 應在 JWT auth 之前執行,否則 S2S endpoint 只受 IP 級別限制

  • Fire-and-forget goroutine(Admin Audit、GDPR Export、Dungeon S3 Upload)是 P0 風險:無 WaitGroup 追蹤、無背壓、無 graceful shutdown

  • security_events 日期分區只到 2035 年,無滾動策略,P1 運維風險

  • JIT 盲點:StartBattle 沒有 DB 層唯一約束,同一用戶並發兩個 battle session 可導致重複獎勵

  • 架構合規總分 9.6/10;P2 問題僅為 SQL string concatenation for whitelisted table/column names,無真實安全風險

  • Publisher 9 階段 graceful shutdown 優於 Game Server 的 3 階段,更細粒度

技術細節

Game Server (cmd/twirpserver)

  • Redis optional fallback — 允許在 Redis 不可用時降級運作
  • ConfigManager FATAL required — 配置載入失敗直接終止
  • 3-stage shutdown: PreStop 5s → HTTP drain → infra cleanup

Publisher

  • 9-stage shutdown — 比 Game Server 更細粒度的優雅關閉
  • JWT keys loaded unconditionally
  • Production-only IAP webhook verifier enforcement

DB 寫入路徑(每次操作的查詢數)

操作 查詢數
ConsumeItems 7q
EndBattle Victory 16q
CompleteChapter 12q
SellItem 5q
CreateAccount 4q

並發問題(P0)

  • GDPR export — 無 semaphore 上界,可同時啟動數千 goroutine
  • Admin audit — fire-and-forget 無 WaitGroup 追蹤
  • Dungeon S3 upload — pool 滿時 silent drop,不報錯

架構合規

10 個 module 全部通過合規掃描:無 Nakama import 洩漏、Wire DI 正確、Twirp adapter compile-time check 全部存在。

What Changed

對整個 MatchRPG Server 專案進行了完整的生產就緒稽核,派遣 4 支專門 Agent 並行執行:(1) 啟動路徑追蹤,(2) DB Schema 與寫入路徑量化,(3) 並發與失敗模式分析,(4) 架構合規全掃描,加上 1 支 JIT 盲點測試 Agent。識別出 6 個 P0 生產阻斷問題、12 個 P1 高優先問題,評定最終分數 82/100。

So What

這次稽核揭示了系統在 1M CCU 下會遇到的真實瓶頸:DB 寫入容量缺口(7-10x)、CAS 重試放大、無界 goroutine 三大核心問題。沒有這次稽核,這些問題只會在生產壓測時才暴露,代價極高。

Trade-offs

並行 Agent 策略可在同等時間內覆蓋更多審查維度,但每個 Agent 的上下文是獨立的,跨 Agent 的交叉驗證需要主 Agent 彙整。CAS 樂觀鎖 vs 悲觀鎖:CAS 在低衝突下效能優,但高並發熱點(同一用戶快速連點)會造成重試風暴。Redis optional fallback 設計允許降級運作,但 rate limiting 和 session caching 同時失效,生產環境應強制要求 Redis。

Try It Fast

快速驗證 CAS 重試放大問題 — 計算 1M CCU 下的 DB 查詢負載:

ccu = 1_000_000
writers = ccu * 0.1        # 10% 寫入活躍
writes_per_sec = writers / 5  # 每 5 秒一次寫入
avg_queries = 10           # 平均查詢數

print(f'Normal load: {writes_per_sec * avg_queries:,.0f} queries/sec')
print(f'With 3x CAS retry: {writes_per_sec * avg_queries * 3:,.0f} queries/sec')
print(f'PG capacity: ~20,000 queries/sec')
print(f'Gap: {writes_per_sec * avg_queries / 20000:.1f}x over capacity')

Recommendation

P0 — 立即修復

  1. Admin audit — 插入外層加 sync.WaitGroup + shutdown hook
  2. GDPR export — 加 semaphore 上界(建議 50)
  3. Dungeon S3 upload — pool 滿時改為 fail-fast 而非 silent drop
  4. StartBattle — 加 DB 唯一約束防止並發雙 session
  5. Publisher Redis — production 環境改為強制要求
  6. Game Server — production 環境強制要求 PUBLISHER_S2S_URL

P1 — 優先處理

  1. 連接池擴至 DBMaxConns=100
  2. dungeon_player_stats(user_id, last_mismatch_at) 複合索引
  3. 調整 Middleware 順序使 rate limiting 在 JWT auth 之前

長期

  1. 規劃讀寫分離(已有 readerPool 架構)
  2. 實作 in-process fallback rate limiter

本文檔由 Semi-Brain 自動生成

Session ID: 95c980e8-1c4d-4527-908a-2db6715a4bc9

分析信心度: 95%