跳轉到

架構概覽

4pass 架構

4pass 是一個生產級 SaaS 平台,將 TradingView 與多個券商 API 串接,實現 Pine Script 策略的自動化下單執行。系統從第一天起就為水平擴展而設計——每個元件都是無狀態的,每個瓶頸前面都有佇列,每個擴展層級只需修改一個 Terraform 變數。目前運行在 AWS 上,具備逐使用者 Worker 隔離、無伺服器編排,以及受管理的資料層,可從單一使用者擴展到 100,000+ 位,無需架構重寫。


系統架構

flowchart LR subgraph clients["客戶端"] TV["TradingView"] UI["儀表板"] end subgraph edge["邊緣層"] WAF["WAF + ALB"] end subgraph compute["API 層"] API["FastAPI(ECS 上)"] end subgraph queues["佇列"] SQS["SQS FIFO x2"] end subgraph lambda["編排層"] L["Lambda x5"] end subgraph workers["Worker 層"] W["ECS 任務<br/>每用戶隔離"] end subgraph data["資料層"] Valkey["Valkey"] RDS["Aurora"] KMS["KMS"] end subgraph broker["券商"] B["Shioaji · Gate.io"] end TV & UI --> WAF --> API API --> SQS --> L --> W --> B API --> Valkey & RDS & KMS W --> Valkey

完整的詳細架構請參閱運算與編排資料層


為什麼選擇此架構 — 商業成果

每個架構決策都對應一個商業成果:

技術選擇 商業成果
逐使用者 Worker 隔離 零跨使用者風險 — 券商當機或憑證洩露只影響一位使用者;券商 SDK 連線綁定所必需
無伺服器編排(Lambda) 無單點故障;零運維負擔;每月 $8.50 對比專用編排器執行個體 $30+
Bridge 網路模式(每執行個體 30 個 Task) 對比 Fargate 節省 75%;每使用者成本 $1.27/月使 NT$999/月定價在 96% 毛利率下可持續
Pool 預熱(897ms) 亞秒級啟動意味著在劇烈波動時不會錯過成交 — 直接影響使用者信任和留存
受管理資料層(Valkey Serverless + Aurora) 零資料庫運維;從 1 位使用者自動擴展至 100K,無需容量規劃或 DBA
佇列驅動一切(SQS FIFO) 持久、有序的訊息投遞;即使在 Lambda 擴展事件期間也不會丟失訂單
基礎設施即程式碼(約 80 個 Terraform 資源) 整個環境數分鐘內可重現;擴展到下一層級只需修改 tfvars,而非重寫

設計原則

# 原則 實作方式
1 逐使用者隔離 每位活躍使用者都擁有一個專屬的 ECS Task。券商連線、憑證和故障絕不會跨使用者邊界。
2 無伺服器編排 五個 Lambda 函式處理所有控制平面工作——Worker 生命週期、下單任務、維護、池管理。無需長時間運行的編排程序,不會故障。
3 受管理資料層 ElastiCache Valkey Serverless 和 Aurora PostgreSQL 搭配 RDS Proxy。零節點管理、自動擴展、內建高可用性 (HA)。
4 縱深防禦 WAF → ALB → 應用層驗證(Webhook 4 層驗證)→ 使用 KMS 的逐使用者憑證加密。每一層都假設上層已被攻破。
5 基礎設施即程式碼 約 80 個 Terraform 管理的資源,涵蓋 ECS、Lambda、SQS、VPC、IAM、CloudWatch。每個環境都可透過單一 terraform apply 重現。
6 每一層的成本最佳化 EC2 容量提供者取代 Fargate(節省 75%)、bridge 網路模式提高密度(每個執行個體 30 個 Task)、Valkey Serverless 取代佈建式(按 ECPU 付費)、Pool 預熱取代冷啟動(快 4 倍)。
7 Bridge 網路模式提高密度 Worker 使用 bridge 模式而非 awsvpc,共享主機 ENI。這移除了每個 Task 一個 ENI 的限制,允許單一 EC2 執行個體上運行 30+ 個 Task。
8 佇列驅動一切 API 與 Lambda 之間的 SQS FIFO 將請求接收與處理解耦。熱路徑上無直接的 Lambda 呼叫——所有工作都通過持久化佇列流轉。

元件摘要

元件 技術 用途 關鍵指標
前端 Vue 3 + Vite 儀表板、策略管理、帳戶設定 SPA 透過 FastAPI 靜態掛載提供
API FastAPI on ECS (m6i.large) REST 端點、Webhook 接收、身份驗證 8 個 Gunicorn Worker,驗證路由 p99 < 50ms
編排 — worker_control Lambda (Python) 透過 SQS FIFO 啟動/停止/認領 Worker 50-500 並行數,冷啟動至就緒中位數 897ms
編排 — order_tasks Lambda (Python) 背景成交確認、訂單狀態管理 50-500 並行數,180s 可見性逾時
編排 — maintenance Lambda (Python) 扇出協調器,用於孤立 (orphan) 偵測 EventBridge 每 60 秒,單次呼叫
編排 — maintenance_worker Lambda (Python) 處理個別孤立標記/任務批次 100-500 並行數,平行執行
編排 — pool_manager Lambda (Python) 將預熱 Worker 池擴展到目標大小 EventBridge 每 5 分鐘
佇列 — worker-control SQS FIFO Worker 生命週期命令,具備訊息去重 可見性 90s,3 次重試後進入 DLQ
佇列 — order-tasks SQS FIFO 成交確認與訂單處理 可見性 180s,3 次重試後進入 DLQ
佇列 — pool-claim SQS Standard 將池中 Worker 分配給使用者 可見性 10s,5 分鐘保留
Worker ECS EC2 (r6i.large) 逐使用者券商連線、訂單執行 每個執行個體 30 個 Task,每個 64 CPU / 384 MB
快取 ElastiCache Valkey Serverless 佇列、心跳、工作階段、速率限制、快取 自動擴展 1 GB → 10 GB、1K → 100K ECPU
資料庫 Aurora PostgreSQL + RDS Proxy 使用者、帳戶、訂單、稽核日誌、工作階段 連線多工、Multi-AZ 就緒
加密 KMS (RSA-4096) 逐使用者憑證加密、HSM 支援 AES-256-GCM 資料金鑰由 KMS 主金鑰包裹
負載均衡器 ALB + WAF TLS 終止、路由、速率限制 每 15 秒健康檢查、WAF 7 條規則
網路 VPC(2 個可用區域) 運算用公有子網路、資料用私有子網路 安全群組強制最小權限

請求流程

一次完整的 Webhook 下單執行——從 TradingView 警報到券商成交:

sequenceDiagram participant TV as TradingView participant WAF as AWS WAF participant ALB as ALB participant API as FastAPI participant Redis as Valkey participant SQS as SQS FIFO participant Lambda as Lambda participant Pool as 池 Worker participant Worker as 使用者 Worker participant Broker as 券商 API TV->>WAF: 1. POST /webhook/tradingview WAF->>ALB: 2. 通過(IP 豁免,規則已檢查) ALB->>API: 3. TLS 終止,轉發 API->>API: 4. 驗證(token → 使用者 → 帳戶 → 訊號) API->>Redis: 5. 檢查 worker:active:{user_id} alt 無活躍 Worker API->>SQS: 6a. 發送到 worker-control.fifo SQS->>Lambda: 6b. Lambda 觸發 Lambda->>Redis: 6c. 檢查池可用性 Lambda->>Pool: 6d. 透過 SQS pool-claim 發送認領 Pool->>Redis: 6e. 設定 Worker 標記(共 897ms) end API->>Redis: 7. 推入訂單到 trading:user:{id}:requests Worker->>Redis: 8. 從佇列取出訂單 Worker->>Broker: 9. 透過券商 API 執行訂單 Broker-->>Worker: 10. 訂單確認 Worker->>Redis: 11. 寫入回應到 trading:response:{req_id} API->>SQS: 12. 排入成交確認(order-tasks.fifo) SQS->>Lambda: 13. Lambda 檢查成交狀態 Lambda->>Redis: 14. 更新最終訂單狀態

逐步說明:

  1. TradingView 發送 POST — Pine Script 策略觸發警報,payload 包含 Webhook 令牌和訊號資料(動作、標的、數量)。
  2. ALB 終止 TLS — 負載均衡器上的 ACM 管理憑證。健康檢查每 15 秒執行一次。
  3. WAF 檢查規則 — TradingView 來源 IP 免於速率限制。所有其他流量通過 SQL 注入、XSS、IP 信譽和速率限制規則。
  4. FastAPI 驗證(4 層) — 令牌查詢 → 使用者解析 → 交易帳戶驗證 → 訊號解析與正規化。任何驗證失敗都會提前返回適當的錯誤。
  5. 檢查 Redis 中的活躍 Worker — 查詢 worker:active:{user_id} 鍵。若存在且 TTL > 5s,表示 Worker 存活。
  6. 沒有 Worker?啟動一個(897ms) — API 發送訊息到 worker-control.fifo → Lambda 接收 → 檢查 Redis 中的池 Worker → 透過 pool-claim 佇列發送認領訊息 → 池 Worker 接收,設定 Redis 標記。總計:中位數 897ms。備援 RunTask:3,659ms。冷啟動 EC2:45-60s。
  7. 將訂單路由到 Redis 佇列 — 將結構化訂單訊息推入 trading:user:{user_id}:requests 列表。
  8. Worker 取出並處理 — Worker 的事件迴圈透過 BLPOP 在毫秒內取出訂單。
  9. 呼叫券商 API — Worker 使用其已建立的券商連線下單。包含倉位翻轉的自動反轉邏輯。
  10. 透過 Redis 回傳結果 — Worker 將結果寫入 trading:response:{request_id},TTL 為 60s。
  11. 背景成交確認 — API 在 order-tasks.fifo 上排入延遲檢查。Lambda 在 30-60 秒後向券商查詢成交狀態,並更新最終狀態。

為什麼選擇這個架構

EC2 優於 Fargate — 節省 75% 成本

Fargate 按 vCPU 和 GB 收取溢價。對於只需要 64 CPU 單元和 384 MB RAM 的 Worker Task,Fargate 的額外成本是巨大的。一個 r6i.large(16 GB、2 vCPU)每小時約 $0.152 可運行 30 個 Worker。同樣 30 個 Worker 在 Fargate 上約需 $0.50/hr。在規模化時,這決定了平台是否能獲利。

Bridge 網路模式 — 每個執行個體 30 個 Task

預設的 awsvpc 模式為每個 Task 分配一個 ENI,在 large 執行個體上硬性限制約 3 個(扣除主機 ENI)。Bridge 網路共享主機的網路堆疊,完全移除此限制。代價是沒有逐 Task 的安全群組——但 Worker 只需要對外存取券商 API,因此這是可接受的。

Lambda 優於 EC2 的編排 — 無單點故障 (SPOF)

長時間運行的編排程序是單點故障。如果它在凌晨 2 點當機,就不會有 Worker 啟動。由 SQS 和 EventBridge 觸發的 Lambda 函式天生具備高可用性——AWS 管理重試、並行和可用性。編排器零運維負擔。

Valkey Serverless — 自動擴展 ECPU

佈建式 ElastiCache 需要容量規劃和為尖峰過度配置。Valkey Serverless 從 1,000 ECPU 自動擴展到 100,000+,僅按消耗的運算量計費。非交易時段,成本降至接近零。開盤時(數千筆同時下單),它無需人工介入即可擴展。

架構論點

每個元件的選擇都是為了在當前規模下最小化運維負擔,同時保留明確的升級路徑通往下一個數量級。沒有任何元件需要替換即可達到 100K 使用者——只需修改配置。