YiBi Dev Docs
架構

Yibi AI 故事機:架構演進與升級規劃書 (Scalability Plan)

版本: 1.0 | 日期: 2026-03-04 策略: 架構預留、按需升級。確保 MVP 階段投入最少資源,同時預留未來高併發擴展的介面。

更新 (ADR-0010): 本文 1.0 版假設裝置通訊使用 MQTT/EMQX;裝置協定已改為 HTTPS event-driven + offline-first(ADR-0010,不部署任何 MQTT broker)。下方 MQTT/EMQX 相關段落均已標註退場,其在高併發下的 HTTPS 等價削峰/scaling 策略為 Tech Lead 待補項,本文尚未定案。


階段一:MVP Demo / Prototype 期 (0 - 50 台裝置)

核心目標:功能驗證、流程走通、快速交付 Demo。

1. 部署架構 (Simple Stack)

  • Backend:
    • App Server (FastAPI): 處理 API 請求,無狀態設計。
    • Worker (Celery): 獨立進程執行 AI 生成任務 (LLM/TTS)。
  • Database: 單一 PostgreSQL(Google Cloud SQL 最小規格)。
  • Cache/Broker: 引入 Redis (7-alpine),作為 Celery 的 Message Broker 與進度快取。
  • 裝置通訊: HTTPS event-driven(裝置主動上傳事件 + offline-first SD queue),不部署 MQTT broker(ADR-0010;原規劃的 EMQX Cloud 方案已退場)。
  • Storage: 直接存取 GCS,音訊透過 FastAPI StreamingResponse 代理(Proxy),暫不配置 CDN。

2. 開發預留點 (Scalability Hook)

  • Stateless API: 程式碼確保不儲存任何 Session 或狀態在記憶體中,方便後續水平擴展。
  • Celery Workers 分離: 任務執行與 API 完全解耦。未來可將 Worker 部署在具備 GPU 或不同規格的機器上。
  • URL 抽象化: 資料庫僅儲存 GCS 相對路徑,由 Utility 函數動態產生 URL,方便未來切換 Proxy 或 CDN。

3. 效能基線優化 (Python-First Optimization)

原則:在考慮語言遷移前,先榨乾 Python + 基礎設施的效能空間。以下項目可在 MVP 階段低成本實施。

優化項目工時影響
Playlist Redis 快取2-3 天Token playlist 查詢延遲 15ms → 1ms(見 E07 spec)
asyncpg 連線池調校1 天防止 DB 連線耗盡,設定 min/max pool size
Celery worker 設定1 天prefork pool、concurrency 與 prefetch multiplier 調校
PostgreSQL EXPLAIN 分析2-3 天對 playlist JOIN、content list、device list 等熱路徑做 EXPLAIN ANALYZE

Playlist Redis 快取策略

Token playlist 是裝置面向的關鍵路徑(SLA ≤ 500ms),且精選/授權內容為 immutable(不會隨時間變化):

  • 快取 Key: playlist:{physical_id} — 包含 category 資訊 + 有序內容清單 + signed URLs
  • TTL: 精選/授權內容 = 30 分鐘(signed URL 有效期 1 小時,留足 buffer);AI 生成內容 = 5 分鐘(可能因新內容生成而變化)
  • 失效時機: 內容生成完成(Celery callback)、Token category 更新(CMS 操作)時主動 DEL playlist:{physical_id}
  • 預期效果: DB JOIN + signed URL 生成(~15ms)降至 Redis GET(~1ms)

階段二:正式上線開賣期 (50 - 2,000 台裝置)

核心目標:系統穩定性、基礎安全性、因應初步併發請求。

1. 基礎設施升級

  • 容器化水平擴展: API 伺服器部署於 Kubernetes (GKE) 或 Cloud Run,設定根據 CPU 負載自動增減實例 (Autoscaling)。
  • 引入 Redis:
    • 將裝置事件時間戳 (last_event_at) 與 Job 進度存入 Redis(ADR-0010 後無 30 秒 heartbeat,改以裝置事件上傳推導在線狀態)。
    • 減輕 PostgreSQL 被細碎 I/O 請求(如裝置事件上傳)拖慢的風險。
  • 初步 CDN 緩存:
    • 針對「精選內容 (Curated/Licensed)」配置 CDN(如 Cloud CDN)。
    • AI 生成內容仍可維持 Proxy 模式以簡化初期設定。

2. 運維增強

  • 監控告警: 引入 Sentry (錯誤追蹤) 與 Cloud Monitoring (效能監控)。
  • 讀取分離準備: 評估資料庫查詢壓力,必要時開啟 PostgreSQL 讀取副本。

3. 效能優化 (Phase 2)

優化項目工時觸發條件影響
K8s/Cloud Run 水平擴展1-2 週API instances CPU > 60%處理 10x 流量
CDN for 精選/授權音訊1 週月頻寬成本 > $200 或播放啟動延遲 > 3s提升 10 倍頻寬吞吐
PostgreSQL read replicas1 週尖峰時段 DB CPU > 70%讀取容量翻倍

CDN 遷移觸發條件與策略

  • Phase 2 目標: 僅遷移「精選/授權」音訊(source_type = curated | licensed),這些內容固定不變,最適合 CDN 快取。
  • 遷移方式: UrlService 已抽象化 URL 生成邏輯,只需擴展為「對 curated/licensed 內容回傳 CDN Signed URL,AI 生成內容維持 Backend Proxy」。
  • CDN 選擇: Cloud CDN + Cloud Storage backend bucket,Signed URL 有效期 1 小時(與現有 GCS Signed URL 一致)。
  • 觸發指標: 月頻寬成本 > $200 音訊播放啟動延遲 P95 > 3 秒。

階段三:穩定成長 / 大量用戶期 (2,000 - 10,000+ 台裝置)

核心目標:因應 Peak Time (19:00~21:00) 衝擊、優化回應時間、降低頻寬成本。

1. 流量削峰與優化 (The High-Concurrence Stack)

  • 全量內容 CDN 覆蓋:
    • 所有音訊播放改為 CDN Signed URL
    • 裝置端直接向邊緣節點請求音訊,API Server 僅處理權限驗證與 URL 簽發,頻寬成本大幅下降。
  • 裝置事件高吞吐處理(待 Tech Lead 設計):
    • 原 EMQX Rule Engine heartbeat bypass 方案已隨 ADR-0010 退場(不再有 MQTT broker 與 30 秒 heartbeat)。HTTPS event ingestion 在高併發下的等價削峰策略(批次寫入/佇列緩衝)待 Tech Lead 評估補上。
  • 資料庫讀寫分離:
    • 配置 PostgreSQL Read Replica。內容瀏覽、歷史記錄查詢等 GET 請求全部導向副本庫。

2. AI 處理能力隔離

  • 獨立 Job Workers:
    • 將 Story/Music Engine 從 API Process 完全分離,建立獨立的 Worker Cluster
    • 尖峰時段可獨立擴展 AI 生成能力,不影響家長操作 App 的流暢度。
  • 統計更新非同步化:
    • play_count 改為「Redis 累加 + 定時批量回寫 DB」,消除高頻寫入造成的資料庫鎖定。

3. 效能優化 (Phase 3)

優化項目工時影響
EMQX Rule Engine heartbeat bypass(已退場,ADR-0010)--原方案依賴 MQTT broker;HTTPS event 等價削峰待 Tech Lead 設計(見下方說明)
全量 CDN 遷移1 週所有音訊(含 AI 生成)走 CDN,Backend 僅簽發 URL
Redis batch write for play_count2-3 天INCR play_count:{content_id} + 每 5 分鐘 cron 批量回寫 DB
Celery worker 叢集隔離1 週AI 生成 job 與 API 背景任務分開佇列,互不搶資源

裝置事件高吞吐處理(待 Tech Lead 設計)

已退場(ADR-0010):本節原為 EMQX Rule Engine heartbeat bypass 的詳細配置(10,000 裝置 × 30 秒 heartbeat ≈ 333 msgs/s,由 EMQX 規則引擎直寫 Redis、繞過 Python)。該方案依賴 MQTT broker 與常駐 heartbeat,已隨 ADR-0010 全面退場。

ADR-0010 後裝置改為 HTTPS event-driven(offline-first,無常駐 heartbeat;在線狀態由 last_event_at 推導)。高併發下的事件 ingestion 削峰策略(批次寫入/佇列緩衝/read-path 快取)為 Tech Lead TODO,尚未定案。

全量 CDN 遷移策略

  • AI 生成內容:生成完成後由 Celery callback 觸發 CDN cache warm-up(pre-sign URL push to CDN origin)。
  • URL 切換UrlService 統一回傳 CDN Signed URL,不再區分 proxy / signed URL 路徑。
  • Device 端影響:裝置的 playlist API 回傳的 audio_url 自動切換為 CDN URL,裝置端無需改動。

階段四:語言遷移評估 (10,000+ 裝置,按需觸發)

核心立場:Python + 基礎設施優化(Phase 1-3)足以支撐 0-10,000 裝置。語言遷移僅在以下觸發條件全部達標後才考慮。

觸發條件(任一達標才啟動評估)

指標門檻值說明
Playlist query P99 延遲> 200ms(已加 Redis 快取)Python 處理本身成為瓶頸
單一 instance 同時裝置連線> 5,000Python 每連線記憶體 ~50KB vs Go ~8KB
API instances 月運算成本> $2,000語言效率差異開始影響成本
預估時間點不早於 50,000+ 活躍裝置

唯一候選:Go Device Gateway 微服務

若觸發條件達標,僅將以下 4-5 個裝置面向的 stateless read endpoints 抽出為獨立的 Go 微服務:

  • GET /tokens/{physical_id}/playlist(NFC 感應熱路徑)
  • GET /devices/{device_id}/status(Redis read)
  • POST /events(裝置事件上傳;指令改由 response 的 pending_actions 下發,ADR-0010 取代原 MQTT command publish)
  • 裝置事件 ingestion worker(HTTPS event-driven;原 MQTT heartbeat subscriber 已退場)

介面邊界

  • 共用 JWT secret 做 device_token 驗證
  • Read-only 存取 PostgreSQL + Redis
  • 不處理:內容生成、auth、家庭管理、CMS、音訊 proxy

工程成本:~8-12 人週,含雙語言 CI/CD pipeline、共用 schema migration 協調。

前提條件:Phase 1-3 的 Python 優化都已實施且仍有瓶頸。團隊至少 8-10 位後端工程師。

多語言服務代價

  • 兩套 CI/CD pipeline、依賴管理、安全審計
  • PostgreSQL schema migration 需跨語言協調
  • JWT 驗證、錯誤碼、分頁慣例需雙語言實作
  • 團隊需同時維護 Python + Go 兩個生態系

升級里程碑與觸發條件表

升級動作階段觸發條件 (指標)預期效果
Playlist Redis 快取Stage 1裝置數 > 10(預設啟用)查詢延遲 15ms → 1ms
asyncpg 連線池調校Stage 1預設啟用防止連線耗盡
引入獨立 RedisStage 2裝置數 > 100 或 API 延遲 > 1s減輕 DB 負載,在線狀態判定更即時
CDN for 精選/授權音訊Stage 2月頻寬成本 > $200 或播放延遲 > 3s提升 10 倍頻寬吞吐
DB 讀寫分離Stage 2尖峰時段 DB CPU 佔用 > 70%讀取容量翻倍
EMQX Rule Engine bypass(已退場,ADR-0010)Stage 3--HTTPS event 等價削峰待 Tech Lead 設計
全量 CDN 遷移Stage 3月頻寬成本 > $500Backend 僅簽發 URL
Redis batch play_countStage 3play_count 寫入 > 50/s消除高頻 DB 寫入
Worker 叢集分離Stage 3Job 排隊等待時間 > 2 分鐘AI job 不搶 API 資源
Go Device GatewayStage 4Playlist P99 > 200ms 或 同時連線 > 5,000最小化每連線記憶體

開發團隊規範 (MVP Phase)

為了支持上述演進,開發團隊在 MVP 階段必須遵守:

  1. 無狀態設計: 絕不在應用程序記憶體中儲存裝置狀態。
  2. 路徑抽象: 存 path,不存 domain
  3. 異步優先: 凡涉及 LLM 或 TTS 的任務,一律封裝於 generation_jobs,絕不阻塞 API 回應。

On this page