
「用 Lambda 就不用管 server 了!」——這句話只對了一半。你確實不用管 server,但你要管的東西一點也沒少,只是換了一批。
結論:另一種形狀,先講怎麼分工
我的經驗法則:同步且短暫的用 Lambda,非同步或長時間的用 ECS,排程的用 EventBridge + Lambda。純 Serverless 很少見,生產環境多數是混的。
然後是四個 Serverless 特有的坑,每一個在 ECS 那個世界不存在:
- 一次呼叫最多 15 分鐘、同步回應最多 6 MB
- 並行預設 1,000,但前面的 API Gateway 預設放 10,000 rps 進來——官方自己寫這兩個對不上
- 接了 VPC 就沒有網路,要 NAT 或 endpoint;閒置 14 天後下一次呼叫會失敗
- 每個並行環境自己開資料庫連線——1,000 並行就是 1,000 條,這正是 RDS Proxy 被做出來的原因
一、什麼場景適合
| 適合 | 不適合 |
|---|---|
| 短 request 的 API handler | WebSocket 之外的長連線、常駐 worker |
| S3 上傳後處理、佇列消費 | 超過 15 分鐘的處理(影片轉檔) |
| 排程任務 | 需要 GPU、高 CPU 的計算 |
| 流量極不穩定、大多時候是零的東西 | 流量穩定且高——ECS 塞滿反而便宜 |
最後一列是判斷的核心:Serverless 的價值是「不用就不付」,流量一直都在的服務用它不划算。
二、四個硬限制,全在官方配額頁
1. 時間與大小:一次呼叫最長 900 秒(15 分鐘);記憶體 128 MB 到 10,240 MB,1,769 MB 等於一個 vCPU(CPU 跟著記憶體給,要更多 CPU 就加記憶體);同步呼叫的請求和回應各 6 MB,非同步 1 MB。超過 15 分鐘的工作不是 Lambda 的事,是 ECS RunTask 或 Step Functions 的事。
2. 並行:預設 1,000 個並行執行環境(新帳號更低,依用量自動放寬);每個 function 每 10 秒最多再長 1,000 個。官方在配額頁末尾自己寫了這段:「API Gateway 預設節流是每秒 10,000 個請求,而 Lambda 預設並行是 1,000。因為這個不對稱,可能有比 Lambda 能處理的更多請求從 API Gateway 進來。」——前門開得比後門大。上線前先申請並行配額,或在 API Gateway 那層把節流設到 Lambda 吃得下的量。
3. 接 VPC 的代價:官方——Lambda 預設有公網;一旦接到你的 VPC(為了連 RDS、ElastiCache),它就只能連 VPC 內的東西,要上網或叫其他 AWS 服務得走 NAT 或 endpoint,跟 第 2 篇的 private subnet 一樣。而且 Lambda 要為你建一張 Hyperplane ENI,建的時候 function 是 Pending 狀態,可能要幾分鐘;閒置 14 天 Lambda 會回收 ENI、function 變 Inactive,下一次呼叫會失敗,要再等 ENI 建好。低頻的 VPC Lambda(每月跑一次的報表)會踩這個。
4. 資料庫連線:每個並行環境是獨立的程序,各自開自己的連線。1,000 並行打 PostgreSQL 就是 1,000 條連線——比 ECS 擴容那個問題(第 6 篇)更兇,因為 Lambda 擴得更快、更碎。RDS Proxy 一開始就是為這個場景設計的;但 第 6 篇講的 pinning 問題在這裡一樣存在,PostgreSQL + prepared statement 要先量。
三、Cold start:存在,但先看你的 SLA
Function 一段時間沒被呼叫會被回收,下次呼叫要重新啟動——這就是 cold start。網路上那些「各語言 cold start 幾毫秒」的表不要信:沒來源,而且跟 image 大小、初始化程式碼、記憶體設定都有關,你自己量才算數。
我的判斷是:大部分場景不需要 Provisioned Concurrency。cold start 只在第一次和擴容時發生,之後的 warm invocation 是毫秒級。API 對延遲極度敏感才花這個錢:
aws lambda put-provisioned-concurrency-config --function-name hello-api \
--qualifier prod --provisioned-concurrent-executions 5四、EventBridge:事件匯流排與排程
EventBridge 是事件路由器:你的服務發一個事件,它依規則送到對的目標。跨服務的「領域事件」放這裡——訂單成立要同時通知點數、會員、推播,發一個事件、各自訂閱,比同步一個一個呼叫乾淨。
aws events put-rule --name order-created --event-bus-name my-app-events \
--event-pattern '{"source":["my-app.orders"],"detail-type":["OrderCreated"]}'
aws events put-targets --rule order-created --event-bus-name my-app-events \
--targets '[{"Id":"process-order","Arn":"arn:aws:lambda:ap-northeast-1:123456789012:function:process-order"}]'排程用 EventBridge Scheduler,有時區參數——不用再寫 UTC 自己換算,直接寫 Asia/Taipei:
aws scheduler create-schedule --name daily-report \
--schedule-expression "cron(0 9 * * ? *)" --schedule-expression-timezone "Asia/Taipei" \
--target '{"Arn":"arn:aws:lambda:ap-northeast-1:123456789012:function:daily-report","RoleArn":"arn:aws:iam::123456789012:role/scheduler-role"}' \
--flexible-time-window '{"Mode":"OFF"}'非同步呼叫的失敗要有地方去:EventBridge 或 SQS 觸發 Lambda,處理失敗會重試,重試完還是失敗的訊息要接死信佇列或 destination——不接就是無聲消失。這條跟 ECS 那邊的佇列一樣,第 7 篇的「死信佇列非空就告警」在這裡同樣適用。
API Gateway 選 HTTP API 還是 REST API 一句話:要 WAF、usage plan、快取才選 REST,其他用 HTTP API。價格差看定價頁,這篇不寫百分比——那會變。
這篇的驗證標準
| 主張 | ❌ 不算 | ✅ 算 |
|---|---|---|
| 並行夠 | 「應該夠」 | 壓測到預期尖峰,看 Throttles 指標為零;API Gateway 節流設了 |
| VPC Lambda 不會卡 | 能連到 RDS | 閒置 14 天後呼叫一次,確認第一次失敗被重試接住 |
| 連線數不爆 | 用了 RDS Proxy | Proxy 的釘住指標接近零;資料庫連線數 << 並行數 |
| 失敗不會消失 | 有重試 | 故意丟一則會失敗的事件,確認出現在死信佇列 |
實戰 Checklist
- 超過 15 分鐘、超過 6 MB 的不用 Lambda
- 並行配額申請到預期尖峰;API Gateway 節流對齊 Lambda 並行
- VPC Lambda 有 NAT 或 endpoint;低頻的接一層重試
- 連 RDS 走 RDS Proxy,且量過釘住率
- 非同步觸發都接死信佇列;死信非空就告警
從 K8s 過來的話
Lambda 對 Knative Serving 或 OpenFaaS,SQS + Lambda 對 KEDA 的事件驅動擴縮,EventBridge Scheduler 對 CronJob,Step Functions 對 Argo Workflows。但心智差最多的是「沒有常駐程序」——K8s 上你習慣的連線池、記憶體快取、背景執行緒,在 Lambda 都不保證活過這次呼叫。這篇的四個坑有三個是從這裡來的。
相關文章
- 上一篇 SSM,下一篇 CD
- 另一種形狀的對照: EKS(常駐程序那一邊)
- 概念層:Serverless、Serverless vs Server 概念篇、實戰篇
Serverless 最大的價值不是「不用管 server」,是「讓你只付你真正用到的錢」——前提是你的流量真的有時候是零。
