跳轉到

Preview Environment 多 PR 並行隔離架構設計:Redis / DB / Istio 路由決策 + 文檔治理拆解

文檔資訊

  • 分類: architecture
  • 難度: advanced
  • 預估閱讀時間: 18 分鐘
  • 標籤: preview-environment, ci-cd, redis-isolation, istio, postgresql-schema, kubernetes, game-server, pr-environment, docs-governance, 32-superseded

摘要

為遊戲伺服器專案設計 PR-level Preview Environment 隔離方案,解決多功能並行開發時 Redis、PostgreSQL、Istio 路由互相干擾的問題。最終採用 Redis logical database (SELECT N)、PostgreSQL schema per PR、Istio header-based routing 三層隔離策略。同時完整拆解 32_CI_Pipeline_Design.md——該文件已被認定為治理違規的漂浮設計稿,其內容分別移至 Infra 25_、Architecture 25_,或直接刪除,32_ 本身改為 Superseded 狀態。

關鍵學習

  • Redis 16 個 logical database 可實現零程式碼改動的 PR 隔離,比 key prefix 侵入性更低

  • Game DB 必須 per-PR 隔離(防止髒資料),Publisher DB 可與 dev 共用(帳號資料不造成功能異常)

  • Header-based routing(方案A)比 wildcard subdomain 更適合現階段:不動 DNS/TLS,QA 可在同設備切換 preview env

  • dev 環境也應帶專屬 header x-env: dev 而非依賴 withoutHeaders,避免路由不穩定問題

  • PostgreSQL schema 隔離(SET search_path)比獨立 DB instance 更省資源,migration 由 PR pipeline 自動執行

  • POSTGRES_SCHEMA env var 注入是 infra 層操作,application 透過 connection string 的 search_path 參數無感切換,不需修改 application code

  • staging 和 prod 不需要 x-env header,因為這兩個環境各自獨立部署,沒有多租戶路由需求

  • 32_CI_Pipeline_Design.md 是設計草稿漂浮文件,其內容與 Infra 25_、Architecture 25_ 產生矛盾和重複,應標記為 Superseded 並將內容歸位到正確 owner 文件

  • 文檔治理規範要求每份文件有明確 owner scope,跨 repo 職責不應混入單一 server repo 文件

技術細節

三層隔離策略

Redis 隔離:Logical Database (SELECT N)

每個 PR 分配一個 Redis DB index(db2–db15,共 14 個 PR slot,db0 保留 dev,db1 備用)。

  • 不需修改 application code,只需注入不同的 REDIS_DB 環境變數
  • PR 關閉時執行 FLUSHDB 清理對應 index
  • 上限:同時最多 14 個並行 PR,超過需考慮 Redis Cluster 或 key prefix 方案

PostgreSQL 隔離:Schema per PR

Game DB 必須每個 PR 獨立 schema,因為功能開發會產生髒資料(技能數值、道具邏輯等),造成測試結果不可信。

Publisher DB(帳號系統)可與 dev 共用,帳號資料本身穩定,不會因功能差異產生異常。

-- PR pipeline 自動執行
CREATE SCHEMA IF NOT EXISTS preview_pr_42;
SET search_path TO preview_pr_42, public;

POSTGRES_SCHEMA env var 由 infra 注入,application 透過 connection string 的 search_path 參數無感切換,不需修改 application code

Istio Header-Based Routing(方案 A)

每個環境帶專屬 x-env header:

  • x-env: dev → game-server-dev
  • x-env: pr-42 → game-server-pr-42(preview namespace)
  • staging 和 prod 不需要 x-env,各自獨立部署,無多租戶路由需求

dev 環境必須帶固定 header,不能依賴 withoutHeaders fallback,否則路由不穩定。

# Istio VirtualService
spec:
  http:
  - match:
    - headers:
        x-env:
          exact: "dev"
    route:
    - destination:
        host: game-server-dev
  - match:
    - headers:
        x-env:
          exact: "pr-42"
    route:
    - destination:
        host: game-server-pr-42

每個 VS match 條件獨立,PR 有先後順序不會互相覆蓋。不需新增 ALB,成本不增加。

完整 CI/CD 流程概覽

開發者 Push → ci.yml (L1 Fast Gate: lint/build/unit)
              PR 建立/更新
              integration.yml (L2: 整合測試)
              smoke.yml (L3: Smoke + Bot)
     ┌──────────────┴──────────────┐
     │                             │
  merge to main              加 preview label
     │                             │
  Build + Push               preview-ci.yml
  tag: main-{sha}            tag: pr-{number}-{sha}
     │                             │
  Infra overlay PR           ArgoCD ApplicationSet
  (dev auto-promote)         建立 preview namespace
     │                             │
  ArgoCD sync                ├─ game-server (獨立 DB schema)
  → dev namespace            ├─ publisher (x-env 導回 dev)
                             ├─ PostgreSQL: search_path=preview_pr_{N}
                             └─ Redis: SELECT N (db2-db15)

  Release flow:
  tag vX.Y.Z-rc.N → staging
  tag vX.Y.Z (final) → prod

32_CI_Pipeline_Design.md 治理問題與拆解結論

32_CI_Pipeline_Design.md 被認定為**漂浮設計草稿**,存在以下問題:

  1. 同時描述 Server CI、Infra CD、ArgoCD、Preview Env、環境晉升,owner scope 混亂
  2. tag 策略(vX.Y.Z 不分 rc/final)與 Architecture 25_ 矛盾
  3. 兩種互相矛盾的 promotion 機制(自動開 PR vs Image Updater)
  4. 本文件的 x-env 說明有誤(local CI 不經過 Istio)
  5. 缺少治理必要欄位(last-verified、validation basis、有效 authority)

拆解執行結論(只有兩件實際需做的事):

  1. 32_CI_Pipeline_Design.md 改為 Superseded,metadata 說明被哪些文件取代
  2. 確認 Infra 25_環境晉升與部署流程.md §8.10 包含 Server CI action items(preview-ci.yml)

其餘內容: - Preview env 設計 → 已在 Infra 25_ §8.6 - tag 策略 → 以 Architecture 25_ 為準 - L1/L2/L3 gate → workflow 檔案本身就是文件 - Workflow migration tasks → 執行時處理,不需另立文件

What Changed

架構決策層面:從原始單一 dev 環境升級為支援多 PR 並行的 Preview Environment 架構,明確定義三層隔離:Redis(logical DB SELECT N)、PostgreSQL(schema per PR)、網路路由(Istio x-env header)。新對話確認 staging/prod 不需要 x-env header,因為它們各自獨立部署。

文檔治理層面(新增於本次對話)32_CI_Pipeline_Design.md 被完整審查後認定為治理違規的漂浮設計草稿。其 Preview Env 設計已移入 Infra 25_環境晉升與部署流程.md,tag 策略以 Architecture 25_版本控管與發布策略.md 為準,32_ 本身標記為 Superseded。這是舊版文檔未涵蓋的重要後續。

技術澄清層面:釐清了 POSTGRES_SCHEMA 是 infra 注入的 env var、application 透過 connection string 無感切換;確認 dev 環境必須主動帶 x-env: dev header 而非依賴 withoutHeaders fallback;local CI smoke test 不經過 Istio,x-env header 只適用於 remote preview/dev ingress 路徑。

So What

這個決策解決了遊戲團隊規模擴大後最常見的開發效率瓶頸:多功能並行開發時環境互相污染。選定方案在**不增加 infra 成本**、不修改 application code 的前提下,實現 PR 級別的完整隔離。

對於遊戲業界,Game DB 髒資料是特別嚴重的問題(技能數值、道具邏輯測試結果失真),因此 per-PR schema 隔離是生產級別必備設計。

文檔治理的教訓同樣重要:設計草稿在完成設計後必須及時歸位到正確的 owner 文件並標記 Superseded,否則隨著時間推移會產生與上游文件的矛盾,反而增加維護成本和閱讀混亂。

Trade-offs

  • Redis 16 DB 上限:最多同時 14 個 PR 隔離(db0=dev, db1 備用),超過需考慮 Redis Cluster 或改用 key prefix 方案
  • PostgreSQL schema 清理複雜度:PR 關閉時需確保 DROP SCHEMA 正確執行,否則累積 schema 會浪費空間
  • Header-based routing 需 client 配合:QA/前端必須在請求中帶正確 header,比 subdomain 方案需要更多工具支援(Postman collection、瀏覽器 extension)
  • publisher DB 共用風險:雖然帳號資料通常穩定,若未來 publisher DB 也有 schema 變更需求,需重新評估是否需要隔離
  • local CI 與 preview env 路徑差異:local smoke/bot test 走 Docker Compose localhost,不經過 Istio;x-env header 只對 remote ingress 路徑有效,兩條路的測試覆蓋面不同

Try It Fast

# PR #42 preview env 啟動時注入的環境變數
export REDIS_DB=2                    # logical database index (db2-db15)
export POSTGRES_SCHEMA=preview_pr_42 # PostgreSQL search_path
export PREVIEW_ENV=pr-42             # Istio routing header value

# PR 關閉時清理
redis-cli SELECT 2 FLUSHDB
psql -c "DROP SCHEMA IF EXISTS preview_pr_42 CASCADE;"
# Istio VirtualService — 所有 dev/preview 環境帶專屬 header
# staging/prod 不需要 x-env(獨立部署,無多租戶路由)
spec:
  http:
  - match:
    - headers:
        x-env:
          exact: "dev"
    route:
    - destination:
        host: game-server-dev
  - match:
    - headers:
        x-env:
          exact: "pr-42"
    route:
    - destination:
        host: game-server-pr-42
# 32_CI_Pipeline_Design.md 標記 Superseded(核心 header 修改)
# 在文件頂部更新 status 欄位:
# status: Superseded
# superseded_by:
#   - D:/phantomarc/MatchRPG_Infra/docs/25_環境晉升與部署流程.md  (preview env, CD flow)
#   - D:/phantomarc/MatchRPG_Architecture/docs/25_版本控管與發布策略.md  (tag strategy)

Recommendation

  1. 立即:確認 32_CI_Pipeline_Design.md 已標記為 Superseded,metadata 指向正確的接替文件(Infra 25_ 和 Architecture 25_)
  2. 立即:確認 Infra 25_環境晉升與部署流程.md §8.10 包含完整的 Server 端 action items(preview-ci.yml trigger、x-env header 注入)
  3. 短期:建立 QA 工具包(Postman collection 預設帶 x-env header),降低 QA 使用 preview env 的門檻
  4. 短期:確認 dev Istio VirtualService 已更新為主動帶 x-env: dev header,移除 withoutHeaders fallback 依賴
  5. 中期:監控 Redis DB index 使用量,超過 12 個並發 PR 時啟動 Redis Cluster 或動態 index 分配機制
  6. 長期(團隊 >10 人):評估升級為 wildcard subdomain(pr-42.dev.matchrpg.internal),徹底省去 header 配置負擔

本文檔由 Semi-Brain 自動生成

Session ID: 770400fc-5a4e-4290-92e5-08106a48b63e

分析信心度: 92%