# ARCHITECTURE.md --- ## 1. 技術選型與決策取捨 | 元件 | 選型 | 核心理由 | 決策理由與取捨 | | :--- | :--- | :--- | :--- | | **開發語言** | **Golang** | 利用輕量級 Goroutine 處理高併發 HTTP 請求,靜態編譯特性大幅簡化部署複雜度。 | 犧牲動態語言開發速度,換取卓越的運行效能與記憶體管理。 | | **訊息佇列 (MQ)** | **Amazon MQ (RabbitMQ)** | 針對耗時較長的 AI 任務,提供精準的 Prefetch Count 控制以防止 Worker OOM;內建 DLX (死信佇列) 完善重試機制。 | 吞吐量雖略遜於 Kafka,但在任務調度、公平分派與複雜路由上更為精確,適合長耗時任務。 | | **資料庫 (DB)** | **Amazon RDS (PostgreSQL)** | 提供強一致性事務保證,支持 JSONB 存儲非結構化資料,未來可擴充向量檢索。 | 我這邊缺失,未限定題目流量問題,在超大流量上選用 NoSQL 可能是較好的選型,但相對後續有複雜查詢就會需要更多的開發或其他 infra 輔助,因此這邊還是先選用 PG,且 OpneAI 現階段也是 PG 起家,後續面對流量問題才分層式的引入 NoSQL | | **快取 (Cache)** | **Amazon ElastiCache (Redis)** | 提供低延遲的任務狀態查詢與 Pub/Sub 機制,支持即時 Token 串流傳輸。| 資料具揮發性,僅作為加速層與通訊層,非永久存儲。 | 本次設計採用 「實體資料庫共享,邏輯層面隔離 (Shared Database, Logical Separation)」 的設計。這與微服務教條中的「一服務一資料庫」不同,其目的在於將任務的生命週期視為單一「聚合根 (Aggregate Root)」,避免在微服務之間進行複雜的分佈式 Join 查詢,提升查詢效能並簡化資料一致性維護。 --- ## 2. 系統架構圖 ![架構圖](https://hackmd.io/_uploads/r1rtqBPTbg.png) --- ## 3. 架構圖流程說明 ### 3.1 使用者上傳音訊 ![用戶上傳](https://hackmd.io/_uploads/SkH808vTbe.jpg) ### 3.2 stt-worker 解析 ![stt 解析](https://hackmd.io/_uploads/H198ewwa-x.jpg) ### 3.2 llm-worker 解析 ![llm 解析](https://hackmd.io/_uploads/HkSLewDT-e.jpg) --- ## 4. 架構特性說明 ### 可擴充性 (Scalability) * **API 層:** 掛載於 **AWS ALB** 後方,根據 ALB Request Count 自動擴展 ECS Fargate 節點。 * **Worker 層:** 結合 AWS ECS Fargate 與 MQ 緩衝機制。系統不單以 CPU 使用率為指標,更監控 「佇列積壓深度 (Queue Depth)」。當任務堆積時,自動觸發 Fargate 橫向擴展 STT/LLM Worker,實現精準的彈性擴縮並優化運算成本。 ### 容錯性 (Fault Tolerance) * **延遲確認機制 (Late ACK):** 確保任務在寫入 DB 成功前不會從 Queue 移除,防止 Crash 導致任務遺失。 * **Dead Letter Queue (DLX):** 自動處理連續失敗的任務,觸發人工介入告警。 * **優雅降級:** 當 MQ 斷線時,API 應任務保留在 PostgreSQL (CREATED),由後台 Sweeper 服務定時補推。 ### 資料一致性 (Data Consistency) * **交易發件匣模式 (Transactional Outbox Pattern):** 確保「DB 更新狀態」與「發送下一階段訊息」在同一個數據庫事務中完成,保證流程不中斷。 * **事件狀態轉移:** MQ Payload 攜帶必要的 Metadata (S3 Key, Transcript),減少 Worker 對 DB 的 Read 壓力。 ### 延遲與效能優化 (Latency & Performance) * **MQ 上的優化**:系統採用 Event-Carried State Transfer 策略:在 STT 完成後,將 transcript 直接封裝於 MQ Payload 中傳遞給 LLM Worker。此舉消除了下游服務回頭 SELECT 資料庫的 I/O 成本。 * **即時回傳**:結合 SSE (Server-Sent Events) 與 Redis Pub/Sub,在 LLM 產出 Token 時即時推播,而非等全部完成才回傳,顯著降低用戶體感延遲。 ### 安全性 (Security) * **S3 私有化:** 採用 S3 Pre-signed URL 機制。前端直接上傳至 S3,防止大檔案塞爆 API Server。簽章中包含嚴格的 Object Key 與 時效性限制,配合 S3 CORS 策略,確保只有授權使用者能在指定時間內完成上傳。 * **身分驗證:** 應在 ALB 與 Middleware 層級實作 Rate Limiting。 ### 可觀測性 (Observability) * **OTel Sidecar:** 每個 Fargate Task 均掛載 OpenTelemetry Collector,採用 **Push Model** 主動推送指標,克服動態環境下 IP 難以追蹤的問題。 * **CloudWatch Logs Insights:** 集中化日誌管理與即時錯誤分析。 --- ## 5. 部署與維運策略 ### 專案結構 (Monorepo) 採用 Go Workspace 結合 Clean Architecture 分層: * `apps/`:包含 `api-server`、`stt-worker`、`llm-worker` 各自獨立的業務邏輯。 * `packages/`:封裝共用的 MQ Client、DB Adapter 與 API 契約。 ### CI/CD 流程 採用 GitHub Actions 進行路徑過濾 (Path Filtering),確保各微服務獨立部署: 1. **git push** 到分支 (Develop/Main) 或打版本號 (v*). 2. **判斷變更:** 根據異動路徑只觸發對應的微服務 Job。 3. **平行處理:** - 執行測試與編譯。 - `docker build` 並推送到對應的 AWS ECR。 - `Render task definition`:更新 ECS 任務定義中的 Image Tag。 - `Deploy to Amazon ECS`:觸發 Fargate 滾動更新,實現零停機部署。 ### 退版機制 (Rollback) * **快速退版:** 透過 AWS 管理介面或 CLI 將 ECS Service 回滾至前一個成功的 Task Definition Revision。 * **版本控管:** Git Tag 觸發的 Prod 部署確保所有 Image 均有明確的版本紀錄可追溯。 --- ## 6. 環境拓樸 * **Dev:** 追蹤 `develop` 分支,用於功能開發與整合測試。 * **Staging:** 追蹤 `main` 分支,模擬 Prod 環境供 QA 驗收。 * **Prod:** 由 Git Tag 觸發,具備完整的 Auto-scaling 與 CodeDeploy 藍綠部署支援 (建議)。 ## 彈性設計 * 插拔式任務設計: 基於 RabbitMQ 的 Topic 路由機制,未來若需增加如「語音情感分析」或「影像辨識」模組,僅需新增訂閱對應 Topic 的 Worker 即可,無需修改核心 API Server 代碼。 ## 延伸優化 - 因為沒有過多的限縮題目(與面試官討論或我主動限制),因此在這個開放式的架構設計下有些優化空間 - 檔案大小限制問題 - 如果不限制這樣在音訊處理上會需要做切割平行化的去做 stt 在合併