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 replicas | 1 週 | 尖峰時段 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請求全部導向副本庫。
- 配置 PostgreSQL Read Replica。內容瀏覽、歷史記錄查詢等
2. AI 處理能力隔離
- 獨立 Job Workers:
- 將 Story/Music Engine 從 API Process 完全分離,建立獨立的 Worker Cluster。
- 尖峰時段可獨立擴展 AI 生成能力,不影響家長操作 App 的流暢度。
- 統計更新非同步化:
play_count改為「Redis 累加 + 定時批量回寫 DB」,消除高頻寫入造成的資料庫鎖定。
3. 效能優化 (Phase 3)
| 優化項目 | 工時 | 影響 |
|---|---|---|
| -- | 原方案依賴 MQTT broker;HTTPS event 等價削峰待 Tech Lead 設計(見下方說明) | |
| 全量 CDN 遷移 | 1 週 | 所有音訊(含 AI 生成)走 CDN,Backend 僅簽發 URL |
| Redis batch write for play_count | 2-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,000 | Python 每連線記憶體 ~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 | 預設啟用 | 防止連線耗盡 |
| 引入獨立 Redis | Stage 2 | 裝置數 > 100 或 API 延遲 > 1s | 減輕 DB 負載,在線狀態判定更即時 |
| CDN for 精選/授權音訊 | Stage 2 | 月頻寬成本 > $200 或播放延遲 > 3s | 提升 10 倍頻寬吞吐 |
| DB 讀寫分離 | Stage 2 | 尖峰時段 DB CPU 佔用 > 70% | 讀取容量翻倍 |
| Stage 3 | -- | HTTPS event 等價削峰待 Tech Lead 設計 | |
| 全量 CDN 遷移 | Stage 3 | 月頻寬成本 > $500 | Backend 僅簽發 URL |
| Redis batch play_count | Stage 3 | play_count 寫入 > 50/s | 消除高頻 DB 寫入 |
| Worker 叢集分離 | Stage 3 | Job 排隊等待時間 > 2 分鐘 | AI job 不搶 API 資源 |
| Go Device Gateway | Stage 4 | Playlist P99 > 200ms 或 同時連線 > 5,000 | 最小化每連線記憶體 |
開發團隊規範 (MVP Phase)
為了支持上述演進,開發團隊在 MVP 階段必須遵守:
- 無狀態設計: 絕不在應用程序記憶體中儲存裝置狀態。
- 路徑抽象: 存
path,不存domain。 - 異步優先: 凡涉及 LLM 或 TTS 的任務,一律封裝於
generation_jobs,絕不阻塞 API 回應。