跳轉到

ConfigManager Fail-open Anti-pattern

概念概覽

問題根源

核心知識

問題根源

main.go:198 ConfigManager 初始化失敗只記錄 warn 並繼續啟動。但系統中有兩個 fail-closed 依賴

  • player_inventory_service.go:961:限時道具發放直接讀取 config,init 失敗 → nil pointer → runtime panic
  • dungeon_service.go:291:dungeon config 取用同樣是 fail-closed 依賴

正確設計原則

fail-open 元件:Redis rate limiter(Redis 故障 → 跳過限速,可用性優先)
fail-closed 依賴:ConfigManager(失敗 → 某些功能會 panic,不可繼續啟動)

修正:在 production 環境,ConfigManager init 失敗應呼叫 log.Fatal,確保 pod crash 並觸發 k8s restart,而不是啟動一個半壞的 server。

fail-open 僅適合本地開發環境,確保開發者不需要完整依賴就能跑起服務。

經驗教訓

  • 設計 fail-open 元件時,必須明確列出所有下游是否有 fail-closed 依賴

  • startup 的 warn-and-continue 是隱性的 fail-open 設計,需要特別審查

  • production 環境讓服務以損壞狀態啟動,比 crash 重啟更危險

常見陷阱

  • 將 fail-open 作為「寬鬆」的預設行為,未區分 production 和 development 環境

  • 初始化錯誤只 log 不 fatal,導致服務看似正常啟動但實際上缺失關鍵依賴

最佳實踐

  • 每個可選依賴在初始化時明確標記為 fail-open 或 fail-closed,並在 code review 中審查

  • production 環境的 startup 代碼應有明確的 fatal 守衛,非可選依賴一律 fatal

  • 使用環境變數區分 production fatal vs development warn-and-continue

相關概念

來源 Sessions

日期 Session 貢獻摘要

| 2026-03-17 | 056f9176-f6b2-4663-9b7e-19679837f204 | 具體說明了 ConfigManager fail-open 在有 fail-closed 依賴場景下為何是 P0 bug,以及 startup fatal 的正確設計 |


本概念頁面由 Semi-Brain Wiki 系統自動維護

最後更新: 2026-03-17