iT邦幫忙

2026 iThome 鐵人賽

DAY 18
0
自我挑戰組

30 天的 SAA 學習筆記系列 第 18 篇

Day 18 - 解耦與無伺服器整合 Lambda:Serverless 執行模型與限制

  • 分享至 

  • xImage
  •  

AWS Lambda 是 AWS 的 serverless(無伺服器)運算服務:使用者只需要上傳程式碼,並設定在什麼情況下執行它;執行程式碼所需的伺服器,由 AWS 負責準備、維護和擴展。

Lambda 裡的一段程式碼稱為一個函式(function)。函式平常不執行,也不計費;只有在指定的事件發生時(例如 S3 有新檔案上傳、API 收到請求),Lambda 才執行它,並依實際執行的時間計費。

無伺服器並非指不存在伺服器,而是指伺服器的佈建、維護與擴展皆由 AWS 負責,使用者無須、也無法直接管理底層伺服器。

這篇依序整理 Lambda 的運作方式與限制:

段落 內容
🆚 Lambda 與 EC2 兩種執行程式的方式差在哪裡
⚡ 呼叫方式 函式怎麼被執行:同步、非同步、event source mapping
🧱 執行環境 函式實際在哪裡執行,執行完之後會怎樣
📈 併發 很多請求同時進來時,Lambda 怎麼處理,上限是多少
🥶 Cold start 為什麼有些請求的回應特別慢,怎麼改善
⚙️ 記憶體與限制 函式能使用多少資源,最久能執行多久
💰 計費 費用怎麼計算
🌐 VPC 函式怎麼連到 VPC 裡的資源
🌍 邊緣 在 CloudFront 邊緣節點執行程式:Lambda@Edge 與 CloudFront Functions

🆚 Lambda 與 EC2

Day 8 的 EC2 也能用來執行程式。兩者的差別在於誰管理伺服器,以及費用怎麼計算:

EC2 Lambda
使用者要管理的 instance type、作業系統、修補程式 程式碼與設定
沒有請求時 執行個體持續運作並持續計費 不佔用資源,不計費
請求變多時 自己設定 Auto Scaling(Day 14)增加機器 自動增加執行環境
單次執行時間 不限 最長 15 分鐘

Lambda 免除了伺服器管理的工作,代價是存在若干使用限制,例如單次執行時間最長 15 分鐘。相關限制整理於後文的記憶體與限制一節。


⚡ 呼叫方式

呼叫與 handler

讓 Lambda 執行一次函式,稱為一次呼叫(invoke)。發出呼叫的一方稱為呼叫端,可能是 API Gateway、S3 這類 AWS 服務,也可能是自己寫的程式。

函式的程式碼裡,必須有一個指定的 function 作為入口,稱為 handler。每次呼叫,Lambda 就執行一次 handler:

def handler(event, context):
    # event:呼叫端傳進來的資料,內容依呼叫端而不同
    #        例如 S3 會傳入新增檔案所在的 bucket 名稱與檔案名稱
    # context:這次執行的相關資訊,例如還剩多少可執行時間
    return "處理完成"    # 回傳值:這次執行的結果

三種呼叫方式

呼叫端把事件交給 Lambda 時,有兩件事可能不同:

  • 呼叫端要不要等函式執行完、拿到回傳值?
  • 事件是呼叫端主動送來,還是 Lambda 自己去取?

依這兩點,Lambda 的呼叫分成三種。下圖由上到下,依序是三種呼叫方式的流程:

https://ithelp.ithome.com.tw/upload/images/20261002/20150978RNJmqIONUK.jpg

1. 同步呼叫(synchronous)

  1. 呼叫端把事件送給 Lambda
  2. Lambda 執行函式,執行期間呼叫端持續等待
  3. 函式執行完,回傳值(或錯誤訊息)送回呼叫端

呼叫端必須等到結果才能繼續,所以同步呼叫用在需要立刻拿到結果的情況。例如 API Gateway 收到使用者的 HTTP 請求後呼叫函式,要拿到函式的執行結果,才能回應使用者。執行失敗時,錯誤直接回給呼叫端,要不要重試由呼叫端決定。

2. 非同步呼叫(asynchronous)

  1. 呼叫端把事件送給 Lambda
  2. Lambda 先把事件存進自己內部的佇列(暫存待處理工作的地方,見 Day 16),並立即回應呼叫端,表示事件已被接收
  3. 之後 Lambda 從佇列取出事件,執行函式

呼叫端在第 2 步就結束了,不會拿到函式的回傳值。S3、SNS、EventBridge(Day 17)都用這種方式呼叫 Lambda:這些服務只負責發出事件通知,不需要取得處理結果。執行失敗時,Lambda 會自動重試 2 次。

3. Event source mapping

前兩種都是呼叫端主動把事件送給 Lambda。但 SQS(Day 16)、Kinesis、DynamoDB Streams 這幾種服務只負責存放資料,不會主動通知任何人,要由使用的一方自己來取。

Event source mapping 是 Lambda 為這類服務提供的功能:

  1. Lambda 在背後定期向來源詢問有沒有新資料,稱為輪詢(poll);圖中的 Lambda poller 即為負責輪詢的元件
  2. 有新資料時,一次取出一批
  3. 把這一批資料交給函式執行

以 SQS 為例,函式處理成功後,Lambda 會替函式把訊息從佇列刪除;處理失敗就不刪除,訊息在 visibility timeout 後重新出現,再被取出處理一次。

三種方式整理如下:

呼叫方式 呼叫端等不等結果 事件怎麼進來 典型來源 失敗時
同步 等 呼叫端送來 API Gateway、ALB、用 SDK 直接呼叫 錯誤回給呼叫端
非同步 不等 呼叫端送來 S3、SNS、EventBridge Lambda 自動重試 2 次;仍失敗可送到 DLQ 或 Destinations(見補充)
Event source mapping 沒有外部的呼叫端 Lambda 主動去取 SQS、Kinesis、DynamoDB Streams 依來源而定;SQS 的訊息會重新出現

**容易混淆的是 SQS:SQS 觸發 Lambda 的實際運作,並非 SQS 將訊息送給 Lambda,而是 Lambda 主動向 SQS 取出訊息。**SNS 觸發 Lambda 則是由 SNS 主動送出事件,屬於非同步呼叫。

另外,非同步呼叫的自動重試、SQS 訊息的重新出現,都可能讓同一個事件被函式處理不只一次。因此函式要設計成同一個事件處理兩次也不會出錯,也就是 Day 16 提過的 idempotent。


🧱 執行環境

函式在哪裡執行

程式碼必須在運算資源上才能執行。Lambda 不開放使用者存取或管理底層伺服器,而是在需要執行函式時,為函式配置一個執行環境(execution environment)。

執行環境是 AWS 為函式配置的隔離運算環境,作用相當於一台專供該函式使用的小型虛擬機器,其中包含:

  • 函式的程式碼
  • runtime:執行該程式語言所需的軟體,例如 Python 3.12、Node.js 20
  • 一塊暫存空間 /tmp

每個執行環境彼此獨立,不共享記憶體,也不共享檔案。

執行環境的三個階段

一個執行環境從建立到被刪除,會經過三個階段:

階段 做的事 發生幾次
Init(初始化) 建立環境、下載程式碼、啟動 runtime,並執行 handler 以外的程式碼 每個環境只有一次
Invoke(執行) 執行 handler,處理一個請求 可以很多次
Shutdown(回收) 環境被 Lambda 刪除 一次

這張表有兩個重點:

  1. **處理完請求,環境不會馬上被刪除。**Lambda 會把環境保留一段時間,這段期間有新的請求進來,就直接用這個環境處理,不用重新 Init。保留多久沒有固定值,由 Lambda 決定。
  2. **一個環境同一時間只能處理一個請求。**環境正在處理請求時,如果又有新的請求進來,新的請求不會排隊等它,而是由 Lambda 另外建立一個新的執行環境來處理。

下圖用時間軸呈現這兩點。橫軸是時間,每一列是一個執行環境:

https://ithelp.ithome.com.tw/upload/images/20261002/201509780NDkykpKPM.jpg

依時間順序看:

  1. 請求 1 到達:目前沒有任何執行環境。Lambda 建立環境 A,先 Init,再處理請求 1。
  2. 請求 2 到達:環境 A 還在處理請求 1,無法接手。Lambda 建立環境 B,同樣先 Init,再處理請求 2。
  3. 請求 3 到達:環境 A 已經處理完請求 1,正在閒置。Lambda 直接用環境 A 處理請求 3,不用再 Init。
  4. 之後沒有新的請求,環境 A、B 閒置一段時間後被回收。

請求 1、2 都必須等待 Init 完成才開始處理,請求 3 則不需要;這段等待時間是後文 Cold start 一節的主題。請求 2 使執行環境增加為 A、B 兩個,則是下一節併發的主題。

把初始化放在 handler 外面

Init 在每個環境只執行一次,所以 handler 外面的程式碼也只執行一次,之後同一個環境處理的每個請求都能共用它的結果。建立成本較高的東西,例如連線其他 AWS 服務用的 client、資料庫連線,通常放在 handler 外面:

import boto3

s3 = boto3.client("s3")        # 在 Init 執行,每個環境只建立一次

def handler(event, context):
    # 每個請求都會執行這裡,直接使用上面建立好的 s3
    s3.get_object(...)

如果放在 handler 裡面,每處理一個請求就要重新建立一次。

/tmp 的情況類似:寫進 /tmp 的檔案,在同一個環境裡會一直存在。但下一個請求不一定分到同一個環境,環境也隨時可能被回收,所以 /tmp 只能放暫時的檔案,不能用來保存需要留下來的資料。


📈 併發

什麼是併發

**併發(concurrency)**是某個時間點上,同時正在處理請求的執行環境數量。

上一段提到,一個環境同一時間只處理一個請求。所以同時有幾個請求正在處理,就需要幾個執行環境,併發數就是多少:

某個時間點,同時有 3 個請求正在處理:
  請求 1 → 執行環境 A
  請求 2 → 執行環境 B
  請求 3 → 執行環境 C
→ 這個時間點的併發數 = 3

執行環境那張圖上的紅色虛線標的也是這件事:在那個時間點,環境 A、B 都在處理請求,併發數是 2。

估算併發數

併發數取決於兩件事:請求進來的速度,以及每個請求要處理多久。

併發數 ≈ 每秒請求數 × 每個請求的執行時間(秒)

例:每秒進來 10 個請求,每個請求要執行 2 秒
    → 任何一個時間點,最近 2 秒內進來的請求都還在處理中
    → 10 × 2 = 20 個請求同時在處理,併發數約 20

同樣的請求量,每個請求執行得越久,需要的併發數就越高。

併發的上限

Lambda 會依請求數自動建立執行環境,不需要像 EC2 那樣自己設定 Auto Scaling。但執行環境的數量不是無限的:

上限 說明
帳號併發上限 每個 Region 預設 1,000,同一個 Region 裡的所有函式共用,可以申請調高
擴展速率 每個函式每 10 秒最多增加 1,000 個執行環境

以上是 AWS 目前公布的數值,之後可能調整。

超過上限的請求,Lambda 不會執行,稱為節流(throttling):同步呼叫的呼叫端會直接收到錯誤(HTTP 429,表示請求太多);非同步呼叫的事件則由 Lambda 稍後自動重試。

Reserved concurrency

帳號的併發上限是同一個 Region 裡所有函式共用的。假設上限是 1,000,函式 A 的請求暴增、用掉 950,函式 B 最多只剩 50 可用;即使函式 B 的流量完全正常,超過 50 的請求也會被節流。

Reserved concurrency 可以替單一函式設定一個固定的併發數。它同時有兩個作用:

作用 說明
保證 設定的額度專屬於該函式,其他函式無法使用
上限 這個函式的併發數最多只到設定值,超過的請求被節流

以上面的例子來說:

  • 替函式 B 設定 reserved concurrency 200:這 200 專屬於 B,即使函式 A 的請求暴增也無法佔用
  • 替函式 A 設定 reserved concurrency 300:A 最多只能同時有 300 個執行環境

**Reserved concurrency 同時是保證,也是上限。**從名稱只能看出保留額度的作用,容易忽略它同時限制了函式本身的併發數。第二個作用常用來保護下游:函式會寫入資料庫時,限制函式的併發數,就等於限制了同時寫入資料庫的數量(VPC 一段會再提到)。

Reserved concurrency 不另外收費。設成 0 時,函式完全不會被執行,可以用來緊急停用一個函式。


🥶 Cold start

為什麼有些請求特別慢

回到執行環境那張圖:請求進來時,如果沒有閒置的環境可用,Lambda 必須建立新環境、先跑完 Init,才能開始處理請求。這段多出來的時間稱為 cold start。請求剛好分到一個已經跑過 Init、正在閒置的環境,就是 warm start,沒有這段額外時間。

Cold start 會發生在三種情況:

  • 函式第一次被呼叫
  • 原本閒置的環境已經被回收
  • 流量上升,需要擴展出更多環境(上一段的併發增加時,每個新環境都是一次 cold start)

Cold start 的長短取決於 Init 要做多少事:

  • Runtime:Java、.NET 這類需要啟動虛擬機器或框架的 runtime,通常比較慢
  • 部署套件大小:套件越大,下載和載入越久
  • handler 外面的程式碼:做的事越多,Init 越久

**Cold start 的影響程度,取決於呼叫端是否等待結果。**非同步呼叫的呼叫端不等待結果,額外的 Init 時間不影響呼叫端;同步呼叫的呼叫端持續等待,cold start 的時間會直接計入回應時間,例如 API 的回應延遲增加。

改善方式

方式 做法 代價
精簡套件與初始化 減少 Init 本身要做的事 要調整程式與相依套件
Provisioned concurrency 預先建立指定數量的環境並跑完 Init,請求進來直接進入 Invoke 不管有沒有請求,這些環境都持續計費
SnapStart 發布版本時先跑完 Init,把記憶體狀態存成快照;新環境直接從快照還原,跳過完整的初始化 支援的 runtime 有限(Java、Python、.NET);程式需處理從快照還原所衍生的狀態問題,例如亂數種子、網路連線

**Provisioned concurrency 能消除 cold start,但也部分放棄了 Lambda 不呼叫即不計費的特性。**為降低離峰時段的閒置費用,可搭配 Application Auto Scaling,依排程或使用率調整 provisioned concurrency 的數量。

SnapStart 適合 Java 這類初始化特別重的 runtime。依目前公布的計費方式,Java 使用 SnapStart 不另外收費;Python 與 .NET 則要另付快照的儲存與還原費用。

另一種做法是以 EventBridge 排程定時呼叫函式,使執行環境維持在已初始化的狀態,避免被回收。此做法只能維持少數幾個執行環境;當流量上升、需要更多併發時,新增的執行環境仍會發生 cold start。


⚙️ 記憶體與限制

只能調記憶體

Lambda 可以設定的運算資源只有一項:記憶體,範圍 128 MB 到 10,240 MB。CPU 不能單獨設定,而是依記憶體大小成比例分配:記憶體約 1,769 MB 時相當於 1 個 vCPU,最高到 6 個 vCPU。網路頻寬也隨記憶體增加。

**Lambda 僅能設定記憶體,CPU 隨記憶體成比例分配。**因此當函式執行緩慢、且瓶頸在 CPU 運算(例如圖片處理、壓縮)時,調高記憶體會同時增加 CPU,執行時間可能隨之縮短,即使原本的記憶體並未用盡。反之,若瓶頸在於等待外部服務回應,調高記憶體並不會縮短執行時間。

限制

項目 上限 說明
執行時間(timeout) 預設 3 秒,最長 900 秒(15 分鐘) 超過就被強制終止。長時間的工作要拆成多次呼叫、交給 Step Functions(把多個步驟串成工作流程的服務,Day 17)協調,或改用 ECS/Fargate 這類容器服務
記憶體 128 MB~10,240 MB CPU 依記憶體成比例分配
/tmp 512 MB~10,240 MB,可以調整 只在該執行環境存在期間有效
部署套件 zip 直接上傳:壓縮後 50 MB;解壓後(含 Layers)250 MB;container image:10 GB 相依套件很大時,改用 container image 或 Layers(見補充)
環境變數 合計 4 KB 密碼這類敏感資訊放 Secrets Manager(Day 24)
呼叫的資料大小(payload) 同步:6 MB;非同步:1 MB 大檔案放在 S3,事件裡只帶物件位置

上表是 AWS 目前公布的數值,之後可能調整,例如非同步的 payload 上限過去長期是 256 KB。

這些限制畫出了 Lambda 適合的工作:時間短、可以拆開、不需要保存狀態,例如檔案上傳後的處理、API 請求、消化佇列裡的訊息。需要長時間連續運算,或要在本機保存狀態的工作,放在 EC2 或容器服務比較合適。


💰 計費

Lambda 的費用分兩部分:

項目 計算方式
請求費 依呼叫次數計費
執行時間費 依 GB-秒 計費:設定的記憶體(GB)× 執行時間(秒),執行時間以 1 毫秒為單位
例:記憶體 512 MB(0.5 GB),每次執行 200 毫秒(0.2 秒),每月呼叫 100 萬次
    執行時間用量 = 0.5 GB × 0.2 秒 × 1,000,000 次 = 100,000 GB-秒

AWS 目前每月提供 100 萬次請求和 400,000 GB-秒的免費額度,以官方公布為準。

執行時間費等於記憶體乘以執行時間,所以調高記憶體不一定比較貴。以一個受 CPU 限制的函式為例:

1,024 MB × 8 秒 = 1 GB × 8 秒 = 8 GB-秒
2,048 MB × 4 秒 = 2 GB × 4 秒 = 8 GB-秒   ← 記憶體加倍、CPU 加倍、時間減半,費用一樣

實際能縮短多少,要看程式能不能用上多出來的 CPU,不一定剛好減半;這個例子要表達的是兩者的計費關係。

Cold start 一節提到的 provisioned concurrency 另行計費:費用依設定的執行環境數量與設定的時間長度計算,與實際是否有請求無關。


🌐 VPC

預設連不到 private subnet

函式常常需要讀寫資料庫,例如 RDS;而 RDS 通常放在 VPC 的 private subnet 裡,不對網際網路開放(Day 5、Day 12)。

在沒有額外設定的情況下,Lambda 函式執行在 AWS 管理的網路中,不在使用者的 VPC 裡。這時函式可以連網際網路,也能連 S3、DynamoDB 這類 AWS 服務的公開端點,但連不到使用者 VPC 裡 private subnet 的資源。

連接 VPC

要連到 RDS,需要在函式的設定裡指定要連接的 subnet 和 Security Group(Day 6)。Lambda 會在這些 subnet 裡建立 ENI(Elastic Network Interface,VPC 裡的虛擬網路卡),函式透過它和 VPC 內的資源通訊。函式的執行角色要有建立和管理 ENI 的權限,AWS 提供 AWSLambdaVPCAccessExecutionRole 這個受管政策。

https://ithelp.ithome.com.tw/upload/images/20261002/20150978onmwOEAnMA.jpg

連接 VPC 之後,Lambda 的 ENI 只有私有 IP,這點會影響對外連線:

  • **放在 public subnet 不等於能上網。**即使連接到 public subnet,ENI 也不會拿到公開 IP,經過 Internet Gateway 一樣連不出去。
  • 函式同時要連網際網路(例如呼叫第三方 API)時,要連接 private subnet,並讓那個 subnet 的預設路由指向 public subnet 裡的 NAT Gateway(Day 5),也就是圖上 ① → ② → ③ 的路線。
  • 只需要連 S3、DynamoDB 這類 AWS 服務的話,也可以用 VPC endpoint,在 AWS 內部網路連線,不必經過 NAT Gateway。

為了高可用,函式要連接多個 AZ 的 subnet,某個 AZ 出問題時,Lambda 仍然可以在其他 AZ 執行。

併發和資料庫連線

連上 RDS 之後,要回頭看併發那一段:每個執行環境各自建立自己的資料庫連線。併發數 400,就可能有 400 條連線同時連到資料庫,超過資料庫能接受的連線數。

常見的處理方式有兩種:

  • 用 reserved concurrency 限制函式的併發數,連線數也就跟著有上限
  • 在函式和資料庫之間加一層 RDS Proxy,由它維護一組連線池,讓很多個執行環境共用少量的資料庫連線

🌍 邊緣:Lambda@Edge 與 CloudFront Functions

一般的 Lambda 函式執行在指定的某一個 Region。如果想在更靠近使用者的地方處理請求,例如在 CloudFront(Day 15)的邊緣節點改寫網址、加上 header,有兩種選擇。

CloudFront 處理一個請求時,有四個可以插入程式的時機:

使用者 ──viewer request──► CloudFront 邊緣節點 ──origin request──► 源站
使用者 ◄─viewer response── CloudFront 邊緣節點 ◄─origin response── 源站

viewer 事件發生在使用者和 CloudFront 之間,每個請求都會觸發;origin 事件發生在 CloudFront 和源站之間,只有快取沒命中、需要回源時才會觸發。

CloudFront Functions Lambda@Edge
可用的時機 只有 viewer request/viewer response 四個都可以
執行環境 輕量的 JavaScript 執行環境 Node.js 或 Python 的 Lambda runtime
執行時間 次毫秒等級 viewer 事件最長 5 秒,origin 事件最長 30 秒
呼叫外部服務 不行 可以
適合 改 header、改寫網址或轉址、簡單的存取控制 較複雜的邏輯、要查外部資料、要在 origin 事件處理
成本 極低,適合大量請求 較高

只是改 header 或網址,用 CloudFront Functions;要呼叫外部服務、邏輯比較完整,或必須在 origin 事件處理,才用 Lambda@Edge。


📌 補充

主題 說明
Layers 把共用的程式庫或相依套件包成獨立的 Layer,多個函式共用,不用每個函式各打包一份;一個函式最多 5 個 Layer
版本與別名(Alias) 函式可以發布多個不可變的版本,Alias 是指向某個版本的名稱。Alias 可以設權重,把部分流量(例如 10%)導向新版本,逐步發布。Provisioned concurrency 和 SnapStart 都設定在版本或 Alias 上
Destinations 非同步呼叫可以分別指定成功和失敗時,把執行結果送到 SQS、SNS、EventBridge 或另一個 Lambda。DLQ 只接失敗的事件;Destinations 成功、失敗都能處理,附帶的執行資訊也比較完整
執行角色(Execution role) 函式執行時使用的 IAM Role(Day 3),決定函式能存取哪些 AWS 資源,例如讀取某個 S3 bucket、從 Secrets Manager 取得資料庫密碼

✅ 小結

段落 解決的問題 重點
呼叫方式 函式怎麼被執行 同步呼叫等待結果、非同步呼叫不等待結果、event source mapping 由 Lambda 主動取出資料;同一事件可能處理不只一次
執行環境 程式跑在哪裡 Init → Invoke → Shutdown;一個環境同時只處理一個請求;Init 的成果可以重用
併發 大量請求同時進入時的處理 併發數 ≈ 每秒請求數 × 執行時間;帳號額度共用;reserved concurrency 是保證也是上限
Cold start 為什麼有些請求慢 新環境要先跑 Init;provisioned concurrency 會持續計費,SnapStart 適合 Java
記憶體與限制 能給多少資源 僅能設定記憶體,CPU 隨記憶體成比例分配;單次最長 15 分鐘
計費 費用怎麼算 請求數 + GB-秒;調高記憶體讓時間變短時,費用可能不變
VPC 怎麼連到私有資源 連接 VPC 後 ENI 只有私有 IP,對外要經 NAT Gateway;連線數用 reserved concurrency 或 RDS Proxy 控制
邊緣 程式放到 CloudFront 簡單、大量用 CloudFront Functions;複雜或 origin 事件用 Lambda@Edge

摘要:Lambda 只在事件發生時,在臨時的執行環境裡執行程式碼,依請求數和執行時間計費。一個環境同時只處理一個請求,所以請求變多就要增加環境,這就是併發;新環境要先初始化,這就是 cold start。15 分鐘的上限和只能調記憶體,決定了哪些工作適合交給 Lambda。


🧠 AI 出題

問題 1

某公司用 Lambda 為上傳到 S3 的高解析照片產生多種尺寸的縮圖,函式目前配置 512 MB 記憶體。監控顯示每次執行約 40 秒,記憶體實際只用到約 300 MB,但 CPU 使用率始終滿載,使用者抱怨縮圖出來得太慢。公司希望以最少的開發工作縮短處理時間,而且整體費用不要明顯增加。

哪一個做法最符合這些需求?

  • A. 為函式設定 provisioned concurrency,讓執行環境事先初始化完成,減少每次處理的等待時間
  • B. 把函式的記憶體配置從 512 MB 調高到 2,048 MB,讓 Lambda 依比例分配到更多的 CPU
  • C. 把縮圖程式改寫成 Step Functions 工作流程,把每種尺寸拆成一個 Lambda 依序執行
  • D. 把函式的 timeout 從 1 分鐘調高到 15 分鐘,讓每次處理都有更充裕的時間可以完成

問題 2

某公司的帳號裡有兩個 Lambda:負責結帳 API 的 checkout,以及月底產生報表的 report,帳號的併發上限是 1,000。每到月底,report 被大量觸發,用掉帳號大部分的併發額度,導致 checkout 被節流、顧客無法結帳;report 的大量併發也打爆了它查詢的資料庫,DBA 要求它同時執行數不得超過 50。公司不希望因此增加固定的費用。

哪兩項做法的組合最符合需求?(選擇兩項)

  • A. 為 checkout 設定 reserved concurrency 300,保證它隨時能使用這 300 個併發額度
  • B. 為 checkout 設定 provisioned concurrency 300,讓 300 個執行環境事先熱著等待請求
  • C. 為 report 設定 reserved concurrency 50,讓它最多只能同時執行 50 個執行環境
  • D. 把 report 的記憶體調降到 128 MB,讓它每次執行時佔用較少的帳號併發資源
  • E. 在 checkout 前面加上一個 SQS queue,讓結帳請求先排隊,再交給 Lambda 依序處理

問題 3

某公司的 Lambda 需要讀寫放在 private subnet 的 RDS for PostgreSQL,同時要呼叫網際網路上第三方金流商的 HTTPS API。工程師把 Lambda 連到 VPC 的 public subnet(route table 有指向 Internet Gateway),結果連得到資料庫,但呼叫金流 API 一律逾時。資安規定資料庫不得暴露在網際網路上,公司要求以最安全的方式修正。

解決方案架構師應該怎麼做?

  • A. 為 Lambda 在 public subnet 的網路介面綁定 Elastic IP,讓它透過 Internet Gateway 對外連線
  • B. 把 Lambda 改連到 private subnet,並讓這些 subnet 的預設路由指向 Internet Gateway
  • C. 把 Lambda 移出 VPC,並把 RDS 改成 publicly accessible,再用 Security Group 限制來源
  • D. 把 Lambda 改連到 private subnet,並讓這些 subnet 的預設路由指向 NAT Gateway

問題 4

某公司的訂單查詢 API 由 API Gateway 呼叫一個以 Java 撰寫的 Lambda。框架初始化很重,遇到 cold start 時回應會拖到 6~8 秒。流量忽高忽低,一天只有幾個小時比較忙。產品團隊要求大幅縮短 cold start 的延遲,但財務部門不願意為閒置的執行環境持續付費,希望以最符合成本效益(MOST cost-effective)的方式處理。

哪一個做法最符合成本效益?

  • A. 設定 provisioned concurrency 50,並用 Application Auto Scaling 依排程調整數量
  • B. 建立每 5 分鐘觸發一次的 EventBridge 規則呼叫函式,讓執行環境保持溫熱不被回收
  • C. 在函式發布的版本上啟用 SnapStart,讓新的執行環境直接從預先初始化好的記憶體快照還原
  • D. 把函式的記憶體調到 10,240 MB,讓初始化階段能分配到最多的 CPU 算力來加速啟動

問題 5

某媒體網站以 CloudFront 提供服務,每月約 50 億次請求。每個請求都要在邊緣依 User-Agent 把網址改寫到行動版或桌面版的路徑,並在回應加上幾個安全相關的 header。這些邏輯都很簡單,執行時間在 1 毫秒以內,也不需要呼叫任何外部服務。公司希望以最符合成本效益的方式實作。

哪一個方案最符合這些需求?

  • A. 以 CloudFront Functions 實作 viewer request 的網址改寫與 viewer response 的 header
  • B. 以 Lambda@Edge 處理 viewer request 與 viewer response 事件,改寫網址並加上 header
  • C. 為 distribution 附加 response headers policy 加上安全 header,並用 cache behavior 的路徑規則分流行動版
  • D. 在 CloudFront 後面加上 API Gateway,由 Lambda 依 User-Agent 改寫網址並在回應加上 header

💡 解答

1. B

Lambda 的 CPU 是依記憶體配置比例分配的。這個函式是 CPU 滿載、記憶體用不完,瓶頸在 CPU,不在記憶體。把記憶體調到 2,048 MB,CPU 算力也跟著變成約 4 倍,CPU 受限的工作通常會接近等比例地縮短執行時間;Lambda 按「執行時間 × 記憶體」計費,時間縮短抵銷了單價的上升,總費用大致持平。只改一個設定,完全不用動程式碼。

A 解的是 cold start,但這裡慢的是每次 40 秒的執行本身,不是初始化。C 把工作拆成多個 Lambda 依序執行,總時間不會變短,還要重寫程式和維護工作流程。D 只放寬時間上限,函式本來就沒有逾時,處理速度一點都不會變快。

2. A、C

reserved concurrency 有兩個作用:替函式保留一塊額度,同時也是它的上限。替 checkout 保留 300,report 再怎麼暴增也搶不走這塊,結帳不會再被節流;替 report 設 50,它最多只能同時跑 50 個,資料庫就不會被打爆。reserved concurrency 本身不收費,符合「不增加固定費用」。

B 也能保證 checkout 有 300 個執行環境可用,但 provisioned concurrency 不管有沒有請求都持續計費,違反「不增加固定的費用」。D 是誤解:併發是以同時執行的環境數量計算的,跟記憶體大小無關,調低記憶體不會減少佔用的併發數,反而可能讓每次執行更慢、佔用更久。E 讓結帳請求排隊,但結帳 API 是同步回應的,顧客要等結果;而且只要 report 仍然佔滿額度,排隊的請求也還是等不到執行環境。

3. D

連到 VPC 的 Lambda,網路介面只有 private IP,就算放在 public subnet 也拿不到公開 IP,所以經過 Internet Gateway 一樣連不出去。正確做法是把 Lambda 放在 private subnet,讓預設路由指向 public subnet 裡的 NAT Gateway:對外連線經由 NAT 出去,資料庫依然留在 private subnet,不會暴露在網際網路上。

A 是誤解:Lambda 的網路介面由 Lambda 服務管理,不支援自己綁定 Elastic IP。B 方向對了一半:Lambda 確實該放在 private subnet,但它的網路介面沒有公開 IP,預設路由指向 Internet Gateway 一樣連不出去;沒有公開 IP 的資源要上網,必須經過 NAT Gateway。C 能讓 Lambda 同時連到資料庫和網際網路,但資料庫變成 publicly accessible,直接違反資安規定。

4. C

SnapStart 會在發布版本時先把執行環境初始化好並做成快照,之後有新的執行環境要啟動時,直接從快照還原,跳過繁重的框架初始化,cold start 可以大幅縮短。Java runtime 使用 SnapStart 不另外收費,沒有請求就不用付錢,符合財務部門的要求。

A 能徹底消除 cold start,但 provisioned concurrency 在設定的時段裡不管有沒有請求都持續計費;流量又忽高忽低,排程很難對準,正是財務部門不想要的「為閒置付費」。B 是常見的土法:定時呼叫只能讓一、兩個環境保持溫熱,流量一上來需要更多並行環境時,新環境還是會 cold start。D 能讓初始化快一些,但每次執行都要按 10 GB 的記憶體計費,成本大幅上升,改善幅度也不如 SnapStart。

5. A

CloudFront Functions 是專門為這種高流量、邏輯簡單的邊緣處理設計的:執行時間短、不需要呼叫外部服務,網址改寫和加上 header 都是它的典型用途。它的單價遠低於 Lambda@Edge,在每月 50 億次請求的規模下,費用差距非常明顯。

B 功能上完全做得到,但 Lambda@Edge 的單價和計費方式都比 CloudFront Functions 貴得多,用在這麼簡單的邏輯上是浪費。C 做對了一半:response headers policy 不用寫程式就能加上安全 header,很適合這部分;但 cache behavior 只依網址路徑比對,看不到 User-Agent,沒辦法決定要把請求改寫到行動版還是桌面版。D 把處理搬回源站那一側,每個請求都要多經過 API Gateway 和 Lambda 才能改寫,不只更貴,也失去在邊緣處理的低延遲。


上一篇
Day 17 - 解耦與無伺服器整合 EventBridge:事件路由服務入門
系列文
30 天的 SAA 學習筆記 共 18 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言