cover

從「永遠在線」到「按次計費」:伺服器架構的典範轉移

在雲端運算出現之前,部署一個應用程式意味著購買或租用實體伺服器,24 小時運行、24 小時付費,不論有沒有人在使用。這個模型簡單直覺,但存在本質性的浪費——凌晨三點沒有流量時,伺服器仍然全速消耗資源。

雲端 IaaS(EC2、GCE)將硬體虛擬化了,但計費邏輯沒有根本改變:你啟動一台虛擬機,就開始按小時計費。真正的典範轉移發生在 2014 年 AWS Lambda 問世:不再為「伺服器運行時間」付費,而是為「程式碼實際執行時間」付費。這就是 Serverless 的核心理念。

但 Serverless 不是銀彈。它在某些場景下成本極低、開發效率極高,但在另一些場景下可能比傳統伺服器更貴、更難除錯。這篇文章完整比較三種主流架構——傳統伺服器、Serverless、Container-as-a-Service(CaaS),幫助你在不同場景下做出正確的選擇。

架構概覽

flowchart TD
    Start{{"流量特性?"}} -->|穩定高吞吐| Q1{{"需要長連線\n或有狀態?"}}
    Start -->|極低或極不穩定| Q2{{"已有 Docker Image?"}}
    Start -->|中等、可預測| Q3{{"團隊有 DevOps?"}}

    Q1 -->|是| Server["傳統伺服器\nEC2 / GCE\n完全控制 + RI 折扣"]
    Q1 -->|否| Q4{{"已有 Docker Image?"}}
    Q4 -->|是| CaaS["CaaS\nCloud Run / Fargate\n容器化 + 自動擴展"]
    Q4 -->|否| Server

    Q2 -->|是| CaaS
    Q2 -->|否| Serverless["Serverless\nLambda / Cloud Functions\n按次計費 + 縮至零"]

    Q3 -->|是| CaaS
    Q3 -->|否| Serverless

    Server ---|"適合:高吞吐 API\nWebSocket / 遊戲\nML 訓練"| S_note[ ]
    Serverless ---|"適合:事件驅動\nWebhook / 排程\nMVP 原型"| SL_note[ ]
    CaaS ---|"適合:微服務\n避免 Vendor Lock-in\n自訂 Runtime"| C_note[ ]

    style S_note fill:none,stroke:none
    style SL_note fill:none,stroke:none
    style C_note fill:none,stroke:none

架構比較總覽

flowchart LR
  subgraph Traditional["傳統伺服器架構"]
    direction TB
    Client1[Client] --> LB[Load Balancer]
    LB --> S1[Server 1\nEC2 / GCE]
    LB --> S2[Server 2\nEC2 / GCE]
    LB --> S3[Server 3\nEC2 / GCE]
    S1 --> DB1[(Database)]
    S2 --> DB1
    S3 --> DB1
  end

  subgraph Serverless["Serverless 架構"]
    direction TB
    Client2[Client] --> APIGW[API Gateway]
    APIGW --> F1["Function A\n(Lambda)"]
    APIGW --> F2["Function B\n(Lambda)"]
    APIGW --> F3["Function C\n(Lambda)"]
    F1 --> DB2[(Database)]
    F2 --> DB2
    F3 --> DB2
    F1 -.->|auto-scale\n0 → N| F1
  end

  subgraph CaaS["Container-as-a-Service"]
    direction TB
    Client3[Client] --> CLB[Cloud Load Balancer]
    CLB --> C1["Container A\n(Cloud Run)"]
    CLB --> C2["Container B\n(Cloud Run)"]
    C1 --> DB3[(Database)]
    C2 --> DB3
    C1 -.->|auto-scale\n0 → N| C1
  end

傳統伺服器維持固定數量的實例;Serverless 以 function 為單位自動擴展(含縮至零);CaaS 則以 container 為單位,兼具容器化的靈活性與自動擴展能力。


核心概念解析

1. 傳統伺服器(EC2 / GCE / VPS)

傳統伺服器架構的特點是完全控制。你擁有作業系統、網路設定、磁碟配置的完整權限,可以安裝任何軟體、開任何 port、跑任何 daemon。

優勢:

  • 完全控制運行環境,可以自訂核心參數
  • 大規模穩定流量下成本可預測,搭配 Reserved Instance 更便宜
  • 支援長時間執行的任務(無執行時間限制)
  • 支援 WebSocket、gRPC 等有狀態連線
  • 不受限於特定雲端供應商的 runtime

代價:

  • 需要自行處理 OS patch、安全更新、監控告警
  • 必須預估容量(capacity planning),低估不夠用、高估浪費錢
  • 擴展速度受限於新實例啟動時間(通常數分鐘)
  • 即使零流量,仍然持續計費

2. Serverless(Lambda / Cloud Functions / Azure Functions)

Serverless 的核心理念是「只管程式碼,不管基礎設施」。你上傳一個 function,平台負責部署、執行、擴展、維運。

優勢:

  • 零維運負擔:不用管 OS、patch、scaling
  • 按次計費:沒有請求就不收錢,適合低流量或流量極不穩定的場景
  • 自動擴展:從 0 到數千個並行實例,毫秒級回應流量暴增
  • 內建高可用:平台本身就是多可用區部署

代價:

  • Cold Start 問題(後詳)
  • 執行時間限制:Lambda 最長 15 分鐘、Cloud Functions 最長 60 分鐘
  • 無狀態限制:function 之間不共享記憶體,必須靠外部儲存
  • Vendor lock-in:程式碼綁定特定平台的 event 格式和 SDK
  • 除錯困難:本地環境難以完全模擬雲端行為

3. Container-as-a-Service(AWS Fargate / Cloud Run / Azure Container Apps)

CaaS 是 Serverless 和傳統伺服器之間的中間路線。你提供一個 Docker image,平台負責執行和擴展。

優勢:

  • 使用標準 Docker image,可攜性高
  • 支援任意語言和框架(不受 runtime 限制)
  • 可以縮至零(Cloud Run),也可以設定最小實例數
  • 比 Lambda 更長的執行時間(Cloud Run 最長 60 分鐘,Fargate 無限制)
  • 相對低的 vendor lock-in(Docker image 可以在任何平台跑)

代價:

  • 需要自行建立 Docker image 和 CI/CD pipeline
  • 成本通常高於純 Lambda(因為以 container 為計費單位)
  • Cold Start 可能比 Lambda 更長(需要拉取和啟動整個 container)

Cold Start 問題深入解析

Cold Start 是 Serverless 架構中最常被討論的問題之一。當一個 function 一段時間沒有被呼叫後,平台會回收其執行環境。下一次請求進來時,平台需要重新配置環境、載入程式碼、初始化 runtime,這個過程就是 Cold Start。

Cold Start 的延遲組成:

  • 容器配置(Container provisioning):50-200ms
  • Runtime 初始化(Node.js/Python/Go):10-100ms
  • 程式碼載入與相依套件初始化:50ms-數秒(取決於套件大小)
  • VPC 網路介面配置(若有啟用 VPC):額外 1-10 秒

不同 Runtime 的 Cold Start 延遲(概略):

  • Go / Rust:< 100ms
  • Python / Node.js:100-500ms
  • Java / .NET:500ms-5s(JVM 啟動和 class loading)

Cold Start 緩解策略:

  1. Provisioned Concurrency(Lambda):預先保持指定數量的 warm 實例,完全消除 Cold Start,但要為預留的實例持續付費。
  2. Keep-warm 定時觸發:每隔幾分鐘用 CloudWatch Event / Cloud Scheduler 發一個空請求,讓 function 保持 warm 狀態。成本低但不能保證在流量暴增時所有實例都是 warm 的。
  3. 最小實例數(Cloud Run):設定 min-instances 為 1 或更多,確保始終有 warm 的 container 等待請求。
  4. 減少套件體積:使用 tree-shaking、layer、slim image 減少載入時間。
  5. 選擇輕量 runtime:Go 和 Rust 的 Cold Start 遠低於 Java。

計費模型比較

傳統伺服器計費方式

計費方式說明折扣幅度適用場景
On-Demand按小時/秒計費,隨開隨停0%(基準價)測試環境、短期專案
Reserved Instance預付 1-3 年,換取折扣30%-60%長期穩定負載
Spot Instance使用閒置容量,價格浮動60%-90%可中斷的批次處理
Savings Plan承諾最低用量,換取折扣20%-40%有穩定基礎用量

Serverless 計費方式

以 AWS Lambda 為例:

  • 請求次數:$0.20 / 百萬次請求
  • 執行時間:$0.0000166667 / GB-秒(128MB 記憶體基準)
  • 免費額度:每月 100 萬次請求 + 40 萬 GB-秒

成本試算範例

# === Serverless vs Traditional Server 成本比較試算 ===
 
# 情境:一個 API 服務,每月處理不同的請求量
# Lambda: 256MB 記憶體,平均執行時間 200ms
# EC2: t3.medium (2 vCPU, 4GB RAM) On-Demand = $0.0416/hr
 
def lambda_monthly_cost(requests_per_month: int) -> float:
    """計算 Lambda 每月成本"""
    free_requests = 1_000_000
    free_gb_seconds = 400_000
 
    memory_gb = 256 / 1024  # 0.25 GB
    exec_time_sec = 0.2     # 200ms
 
    billable_requests = max(0, requests_per_month - free_requests)
    total_gb_seconds = requests_per_month * memory_gb * exec_time_sec
    billable_gb_seconds = max(0, total_gb_seconds - free_gb_seconds)
 
    request_cost = billable_requests * 0.20 / 1_000_000
    compute_cost = billable_gb_seconds * 0.0000166667
 
    return round(request_cost + compute_cost, 2)
 
 
def ec2_monthly_cost(instance_type: str = "t3.medium") -> float:
    """計算 EC2 每月成本(On-Demand)"""
    hourly_rate = 0.0416  # t3.medium us-east-1
    hours_per_month = 730
    return round(hourly_rate * hours_per_month, 2)
 
 
# 不同流量下的成本比較
scenarios = [
    ("低流量", 100_000),
    ("中等流量", 1_000_000),
    ("中高流量", 10_000_000),
    ("高流量", 50_000_000),
    ("超高流量", 100_000_000),
]
 
ec2_cost = ec2_monthly_cost()
print(f"{'場景':<12} {'月請求數':>14} {'Lambda 成本':>12} {'EC2 成本':>10} {'較便宜的':<10}")
print("-" * 65)
 
for name, requests in scenarios:
    lc = lambda_monthly_cost(requests)
    cheaper = "Lambda" if lc < ec2_cost else "EC2"
    print(f"{name:<12} {requests:>14,} ${lc:>10.2f} ${ec2_cost:>8.2f} {cheaper:<10}")
 
# 輸出結果(概略):
# 場景         月請求數     Lambda 成本    EC2 成本  較便宜的
# -----------------------------------------------------------------
# 低流量          100,000      $0.00     $30.37  Lambda
# 中等流量      1,000,000      $0.00     $30.37  Lambda
# 中高流量     10,000,000     $18.13     $30.37  Lambda
# 高流量       50,000,000    $109.63     $30.37  EC2
# 超高流量    100,000,000    $222.93     $30.37  EC2

結論: 在大約 2,000-3,000 萬次請求/月 的交叉點之後,EC2 的固定成本模型開始比 Lambda 的按次計費更划算。但實際的交叉點會因 function 的記憶體需求、執行時間、以及是否使用 Reserved Instance 而大幅變動。


Vendor Lock-in 考量

面向鎖定程度說明
AWS LambdaEvent 格式(API Gateway proxy event)、Layer、Extensions 都是 AWS 專屬
Cloud FunctionsGCP event 格式、與 Firestore/Pub/Sub 的整合方式是 GCP 專屬
Cloud Run標準 Docker image + HTTP,幾乎可以無痛搬到任何平台
EC2 / GCE若使用 cloud-specific SDK(如 AWS SDK)則有鎖定,但 VM 本身可搬遷
Serverless Framework抽象層,理論上可以切換 provider(實務上仍有差異)

降低鎖定的策略:

  • 使用 Hexagonal Architecture / Ports & Adapters,將業務邏輯與雲端 SDK 解耦
  • 使用 Serverless Framework 或 SST 等抽象層
  • 將核心邏輯包裝成獨立的 npm package / Python module,handler 只做 event 轉換
  • 考慮 Cloud Run 等基於 Docker 的方案,可攜性最高

詳細比較表

維度傳統伺服器 (EC2/GCE)Serverless (Lambda/CF)CaaS (Cloud Run/Fargate)
控制程度完全控制 OS、網路、磁碟僅控制程式碼和設定控制 container 內容,不管 host
擴展方式手動或 Auto Scaling Group(分鐘級)自動(毫秒級,含縮至零)自動(秒級,可縮至零)
成本模型按時計費(可 RI/Spot 折扣)按請求次數 + 執行時間按 container 運行時間(可縮至零)
Cold Start無(常駐)有(100ms-10s)有(1s-30s,取決於 image 大小)
最長執行時間無限制Lambda 15 分鐘 / CF 60 分鐘Cloud Run 60 分鐘 / Fargate 無限制
狀態管理可在本地記憶體/磁碟保存狀態無狀態,必須用外部儲存單一請求內有狀態,跨請求無狀態
除錯方式SSH 進去、看 log、用 debuggerCloudWatch Logs + X-RayCloud Logging + 本地 Docker 測試
Vendor Lock-in中(VM 可搬,但 cloud SDK 有鎖定)高(event 格式、SDK 綁定)低(標準 Docker image)
適合的團隊有 DevOps/SRE 能力的團隊小團隊、快速原型有 Docker 經驗、需要彈性的團隊

適用場景指南

Serverless 最適合的場景

  • 事件驅動處理:S3 檔案上傳後觸發縮圖、影片轉檔
  • Webhook Handler:接收 LINE Bot / Slack / GitHub webhook
  • 排程任務:每天凌晨跑報表、同步資料、清理過期 session
  • 低流量 API:內部工具、後台管理 API
  • 原型驗證:快速上線 MVP,不花時間在 infra

傳統伺服器最適合的場景

  • 長時間執行的任務:影片轉碼、ML 模型訓練
  • WebSocket / 即時通訊:需要維持長連線的場景
  • 有狀態應用:遊戲伺服器、需要 in-memory cache 的應用
  • 高吞吐量 API:每秒數千請求的核心 API,固定成本更划算
  • 合規需求:需要特定 OS 設定、磁碟加密、網路隔離

CaaS 最適合的場景

  • 容器化應用需要自動擴展:已經有 Docker image,想要自動 scaling
  • 比 Lambda 需要更多控制:需要自訂 runtime、安裝特殊套件
  • 避免 vendor lock-in:同一個 Docker image 可以跑在任何雲端
  • 微服務架構:每個服務一個 container,獨立部署和擴展

程式碼範例

範例一:AWS Lambda Function(Node.js)

// handler.js — 處理 API Gateway 請求的 Lambda function
import { DynamoDBClient, GetItemCommand } from "@aws-sdk/client-dynamodb";
 
const ddb = new DynamoDBClient({ region: "ap-northeast-1" });
 
export const handler = async (event) => {
  const { httpMethod, pathParameters, body } = event;
  const userId = pathParameters?.id;
 
  try {
    if (httpMethod === "GET" && userId) {
      // 從 DynamoDB 取得使用者資料
      const result = await ddb.send(
        new GetItemCommand({
          TableName: process.env.USERS_TABLE,
          Key: { userId: { S: userId } },
        })
      );
 
      if (!result.Item) {
        return {
          statusCode: 404,
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ error: "User not found" }),
        };
      }
 
      return {
        statusCode: 200,
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          userId: result.Item.userId.S,
          name: result.Item.name.S,
          email: result.Item.email.S,
        }),
      };
    }
 
    return {
      statusCode: 400,
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ error: "Invalid request" }),
    };
  } catch (error) {
    console.error("Error:", error);
    return {
      statusCode: 500,
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ error: "Internal server error" }),
    };
  }
};

範例二:AWS SAM Template 部署設定

# template.yaml — AWS SAM (Serverless Application Model) 部署範本
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: User API with Lambda + API Gateway + DynamoDB
 
Globals:
  Function:
    Runtime: nodejs20.x
    MemorySize: 256
    Timeout: 10
    Environment:
      Variables:
        USERS_TABLE: !Ref UsersTable
 
Resources:
  # API Gateway
  UserApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: prod
      Cors:
        AllowOrigin: "'*'"
        AllowMethods: "'GET,POST,OPTIONS'"
 
  # Lambda Function
  GetUserFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: handler.handler
      CodeUri: ./src
      Description: "取得使用者資料"
      Events:
        GetUser:
          Type: Api
          Properties:
            RestApiId: !Ref UserApi
            Path: /users/{id}
            Method: GET
      # Provisioned Concurrency 以避免 Cold Start
      ProvisionedConcurrencyConfig:
        ProvisionedConcurrentExecutions: 2
      Policies:
        - DynamoDBReadPolicy:
            TableName: !Ref UsersTable
 
  # DynamoDB Table
  UsersTable:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: users
      BillingMode: PAY_PER_REQUEST
      AttributeDefinitions:
        - AttributeName: userId
          AttributeType: S
      KeySchema:
        - AttributeName: userId
          KeyType: HASH
 
Outputs:
  ApiEndpoint:
    Description: "API Gateway endpoint URL"
    Value: !Sub "https://${UserApi}.execute-api.${AWS::Region}.amazonaws.com/prod"

範例三:Cloud Run 部署(Docker Image)

#!/bin/bash
# deploy-cloud-run.sh — 從 Docker image 部署到 Cloud Run
 
PROJECT_ID="my-project"
SERVICE_NAME="user-api"
REGION="asia-east1"
IMAGE="gcr.io/${PROJECT_ID}/${SERVICE_NAME}"
 
# 1. 建置 Docker image
docker build -t "${IMAGE}:latest" .
 
# 2. 推送到 Google Container Registry
docker push "${IMAGE}:latest"
 
# 3. 部署到 Cloud Run
gcloud run deploy "${SERVICE_NAME}" \
  --image "${IMAGE}:latest" \
  --region "${REGION}" \
  --platform managed \
  --allow-unauthenticated \
  --port 8080 \
  --memory 512Mi \
  --cpu 1 \
  --min-instances 1 \
  --max-instances 10 \
  --concurrency 80 \
  --set-env-vars "NODE_ENV=production,DB_HOST=10.0.0.5" \
  --vpc-connector "my-vpc-connector" \
  --timeout 300
 
# 4. 取得服務 URL
SERVICE_URL=$(gcloud run services describe "${SERVICE_NAME}" \
  --region "${REGION}" \
  --format "value(status.url)")
 
echo "Service deployed at: ${SERVICE_URL}"
 
# 5. 驗證部署
curl -s "${SERVICE_URL}/health" | jq .

混合部署模式:核心 API 在伺服器,背景任務用 Serverless

在實務中,很少有團隊全部使用一種架構。最常見的做法是混合部署:將核心 API 部署在傳統伺服器或 CaaS 上,而將背景任務、事件處理等交給 Serverless。

flowchart TD
  Client[Client App] --> ALB[Application Load Balancer]

  ALB --> CoreAPI["Core API\n(ECS Fargate / EC2)\n高吞吐、低延遲"]

  CoreAPI --> DB[(PostgreSQL RDS)]
  CoreAPI --> Redis[(Redis ElastiCache)]
  CoreAPI -->|publish event| SQS[SQS / SNS]
  CoreAPI -->|upload file| S3[S3 Bucket]

  SQS -->|trigger| Worker["Background Worker\n(Lambda)\n圖片縮放、email 寄送"]
  S3 -->|trigger| Processor["File Processor\n(Lambda)\n影片轉檔、CSV 匯入"]

  CW[CloudWatch Events] -->|schedule| Cron["Scheduled Tasks\n(Lambda)\n報表、清理、同步"]

  Worker --> DB
  Processor --> DB
  Cron --> DB

  subgraph "穩定流量 → 固定成本"
    CoreAPI
    DB
    Redis
  end

  subgraph "突發/低頻 → 按次計費"
    Worker
    Processor
    Cron
  end

混合部署的原則:

  • 核心路徑(使用者直接互動的 API)放在伺服器或 CaaS,確保低延遲和穩定性
  • 背景任務(非同步、可容忍延遲)放在 Serverless,節省成本
  • 排程任務(Cron job)放在 Serverless,不需要 24 小時跑一台機器只為了每天執行一次的任務
  • 透過 Message Queue(SQS/SNS/Pub/Sub)解耦核心 API 與背景處理

常見問題與風險

1. Lambda 記憶體與 CPU 的連動性

Lambda 的 CPU 分配是和記憶體綁定的。128MB 記憶體只給很少的 CPU,1,769MB 才等於一個完整 vCPU。如果你的 function 是 CPU 密集型(如加解密、壓縮),增加記憶體可能反而降低總成本,因為執行時間大幅縮短。

2. Timeout 與重試風暴

Lambda 預設會在失敗時重試(非同步呼叫重試 2 次)。如果你的 function 因為下游服務超時而失敗,重試可能造成下游更大的壓力(retry storm)。務必設定合理的 timeout、配合 Dead Letter Queue (DLQ) 處理失敗的事件。

3. 並發限制

Lambda 每個 region 預設 1,000 並發限制(可申請提高)。如果一個 function 吃掉太多並發,可能影響同帳號下其他 function。建議為關鍵 function 設定 Reserved Concurrency。

4. Serverless 的隱藏成本

  • API Gateway 的費用($3.50 / 百萬次請求)往往比 Lambda 本身更貴
  • CloudWatch Logs 的儲存費用會隨著 function 數量增長而快速累積
  • NAT Gateway 費用:如果 Lambda 在 VPC 內需要存取外部服務,NAT Gateway 的費用可能是最大的開支

5. 本地開發體驗

Serverless 的本地開發體驗通常不如傳統伺服器。雖然有 SAM Local、Serverless Offline 等工具,但它們無法完全模擬雲端環境(IAM 權限、Event Source Mapping 等)。建議搭配整合測試環境,在真實雲端環境中驗證行為。

6. 監控與除錯

分散式的 function 架構讓除錯變得更困難。一個請求可能經過 API Gateway → Lambda A → SQS → Lambda B → DynamoDB,要追蹤完整的請求鏈路需要使用分散式追蹤工具(AWS X-Ray、OpenTelemetry)。

7. 部署與版本管理

Serverless function 的部署頻率通常很高(因為每個 function 可以獨立部署),但也因此更容易出現版本不一致的問題。建議使用 Infrastructure as Code(SAM/CDK/Terraform)管理所有 function 的版本和設定。


常見服務 × 架構對照表

以下整理常見服務適合哪種架構。記住,沒有絕對正確的答案——關鍵是理解你的流量特性、延遲需求和團隊能力。

服務類型範例推薦架構原因
即時聊天Slack / DiscordServer需要 WebSocket 長連線
靜態網站 + API個人部落格、Landing PageServerless低流量、event-driven
電商平台Shopify 自建、PChomeServer or CaaS穩定高流量、需要 session 管理
LINE Bot / Webhook聊天機器人、GitHub WebhookServerlessevent-driven,低頻觸發
圖片/影片處理縮圖產生、影片轉檔Serverless非同步處理、突發流量
ML 推論 API圖像辨識、NLP 服務CaaS自訂 runtime、需要 GPU
排程報表每日銷售報表、資料同步ServerlessCron trigger,不需常駐
內部管理後台Admin Dashboard、CMSCaaS or Serverless低流量、使用者數少
IoT 資料收集感測器數據上傳、裝置回報Serverless突發流量、事件驅動
串流服務Netflix、TwitchServer高頻寬、長連線
CI/CD RunnerGitHub Actions Self-hostedCaaS需要 Docker、自訂環境
認證服務 (OAuth)SSO、第三方登入Server or CaaS穩定需求、有狀態 session
搜尋引擎Elasticsearch、站內搜尋Server高記憶體、常駐索引
通知推播Email 通知、App PushServerlessevent-driven、突發流量
資料 ETL Pipeline資料倉儲匯入、日誌分析Serverless or CaaS批次處理、非同步執行

看到規律了嗎? 長連線/高流量/有狀態 → Server,事件驅動/突發/無狀態 → Serverless,需要容器化/自訂 Runtime → CaaS。


決策流程圖

當你在選擇架構時,可以依照以下問題逐步判斷:

  1. 流量是否穩定且高吞吐? → 是 → 考慮 EC2 + Reserved Instance
  2. 需要長連線或有狀態? → 是 → 考慮 EC2 / ECS
  3. 已經有 Docker image? → 是 → 考慮 Cloud Run / Fargate
  4. 流量極低或極不穩定? → 是 → 考慮 Lambda / Cloud Functions
  5. 是事件驅動的背景任務? → 是 → 考慮 Lambda + SQS
  6. 需要快速原型驗證? → 是 → 考慮 Serverless(開發速度最快)

大多數生產環境最終會走向混合架構。關鍵不是選擇「一個最好的」,而是為每個工作負載選擇最適合的部署方式。


延伸閱讀