非同步調用 - AWS Lambda

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

非同步調用

幾個 AWS 服務例如亞馬遜簡單儲存服務 (Amazon S3) 和亞馬遜簡單通知服務 (Amazon SNS)) 會以非同步方式叫用函數來處理事件。當您以非同步方式呼叫函數時,您不需要等待來自函數程式碼的回應。您可以將事件傳遞給 Lambda,而 Lambda 會處理其餘的工作。您可以設定 Lambda 處理錯誤的方式,並可以將叫用記錄傳送到下游資源,例如 Amazon Simple Queue Service (Amazon SQS) 或 Amazon EventBridge (EventBridge),以將應用程式的元件鏈結在一起。

Lambda 如何處理非同步調用

下圖顯示以非同步方式來調用 Lambda 函數的用戶端。Lambda 會先將事件排入佇列,再將事件傳送到函數。

用戶端以非同步方式調用函數。Lambda 會先將事件排入佇列,再將事件傳送到函數。

針對非同步調用,Lambda 會將事件置放在佇列中,並傳回成功回應,其中不包含其他資訊。單獨的程序會從佇列讀取事件,並將事件傳送到您的函數。若要以非同步方式調用函式,請將調用類型參數設定為 Event

aws lambda invoke \ --function-name my-function \ --invocation-type Event \ --cli-binary-format raw-in-base64-out \ --payload '{ "key": "value" }' response.json

如果您使用的是 AWS CLI 版本 2,則需要此cli-binary-format選項。若要讓此成為預設的設定,請執行 aws configure set cli-binary-format raw-in-base64-out。若要取得更多資訊,請參閱《AWS Command Line Interface 使用者指南第 2 版》AWS CLI 支援的全域命令列選項

{ "StatusCode": 202 }

輸出檔 (response.json) 不包含任何資訊,但仍會在您執行此命令時建立。如果 Lambda 無法將事件新增到佇列,錯誤訊息就會顯示在命令輸出中。

Lambda 會管理函數的非同步事件佇列,並在發生錯誤時嘗試重試。如果函數傳回錯誤,則 Lambda 會嘗試多執行函數兩次,且兩次嘗試之間等候一分鐘,而第二次和第三次嘗試之間等候兩分鐘。函式錯誤包含函式程式碼所傳回的錯誤,以及函式執行時間所傳回的錯誤,例如逾時。

如果函式沒有足夠的並行可用來處理所有事件,則額外請求會遭到調節。對於調節錯誤 (429) 和系統錯誤 (500 序列),Lambda 會將事件傳回到佇列,並嘗試再次執行函數長達 6 小時。重試間隔從第一次嘗試後的 1 秒呈指數增加到最多 5 分鐘。如果佇列包含許多項目,Lambda 會增加重試間隔,並降低從佇列讀取事件的速率。

即使您的函數並未傳回錯誤,它也可以從 Lambda 收到相同的事件很多次,因為佇列本身最終一致。如果函式來不及處理傳入事件,也可以從佇列中刪除事件,而不需傳送到函式。確保您的函式程式碼可從容地處理重複的事件,而且您有足夠的並行可用來處理所有調用。

當佇列很長時,新的事件可能會在 Lambda 有機會將其傳送到函數前就已過期。當事件過期時或所有處理嘗試皆失敗時,Lambda 便會捨棄該事件。您可以設定函數的錯誤處理,以減少 Lambda 執行的重試次數,或更快地捨棄未處理的事件。

您也可以設定 Lambda,將調用記錄傳送到另一個服務。Lambda 支持以下目的地以進行非同步調用。請注意,不支援 SQS FIFO 佇列和 SNS FIFO 主題。

  • Amazon SQS - 標準 SQS 佇列。

  • Amazon SNS – 標準 SNS 主題。

  • AWS Lambda - Lambda 函數。

  • Amazon EventBridge- EventBridge 事件總線。

呼叫記錄包含請求和回應 (JSON 格式) 的詳細資訊。您可以為成功處理的事件及所有處理嘗試皆失敗的事件設定個別目標。或者,您可以將標準 Amazon SQS 佇列或標準 Amazon SNS 主題設為捨棄事件的無效字母佇列。針對無效字母佇列,Lambda 只會傳送事件的內容,而不包含回應的詳細資訊。

如果 Lambda 無法將記錄傳送到您已設定的目的地,則會將DestinationDeliveryFailures指標傳送至 Amazon CloudWatch。如果您的組態中包含不受支援的目的地類型 (例如 Amazon SQS FIFO 佇列或 Amazon SNS FIFO 主題),就可能發生這種情形。傳遞錯誤也可能因許可錯誤和大小限制而發生。如需 Lambda 調用指標的詳細資訊,請參閱:呼叫指標

注意

為了防止函數觸發,您可以將函數的預留並行設為零。當您將非同步調用函數的預留並行設定為零時,Lambda 會開始將新事件傳送至設定的無效字母佇列或失敗時的事件目的地,不會進行任何重試。若要處理在預留並行設定為零時傳送的事件,您必須使用來自無效字母佇列或失敗時的事件目的地之事件。

設定非同步調用的錯誤處理

使用 Lambda 主控台設定函數、版本或別名的錯誤處理設定。

設定錯誤處理
  1. 開啟 Lambda 主控台中的 函數頁面

  2. 選擇一個函數。

  3. 選擇 組態,然後選擇 非同步調用

  4. 非同步調用 下方,選擇 編輯

  5. 進行下列設定。

    • Maximum age of event (事件存留期上限) - Lambda 在非同步事件佇列中保留事件的時間上限,最多 6 小時。

    • Retry attempts (重試嘗試) - 當函數傳回錯誤時,Lambda 重試的次數上限 (介於 0 到 2)。

  6. 選擇 儲存

當調用事件超過最大存留期,或所有重試嘗試都失敗時,Lambda 會將其捨棄。若要保留已捨棄事件的副本,請設定失敗事件的目的地。

設定非同步調用的目的地

若要保留非同步調用的記錄,請將目的地新增至您的函數。您可以選擇將成功或失敗的調用傳送至目的地。每個函數都可以有多個目的地,因此您可以為成功和失敗的事件配置單獨的目的地。傳送至目的地的每筆記錄都是包含調用之詳細資訊的 JSON 文件。與錯誤處理設定相似,您可以設定函數、函數版本或是別名的目標。

以下資料表列出針對非同步調用記錄支援的目的地。若要讓 Lambda 成功將記錄傳送至您選擇的目的地,請確定函數的執行角色也包含相關許可。此資料表也說明每個目的地類型如何接收 JSON 調用記錄。

目的地類型 所需的許可 目的地特定 JSON 格式

Amazon SQS 佇列

平方:SendMessage

Lambda 會將調用記錄做為 Message 傳遞至目的地。

Amazon SNS 主題

sns:Publish

Lambda 會將調用記錄做為 Message 傳遞至目的地。

Lambda 函數

InvokeFunction

Lambda 傳遞調用記錄會以承載形式傳遞給函數。

EventBridge

事件:PutEvents

  • Lambda 通過調用記錄作為detail在 PutEvents 調用。

  • source 事件欄位的值是 lambda

  • detail-type 事件欄位的值是 Lambda Function Invocation Result - Success (Lambda 函數調用結果 - 成功) 或 Lambda Function Invocation Result - Failure (Lambda 函數調用結果 - 失敗)。

  • resource 事件欄位包含函數和目的地 Amazon Resource Names (ARN)。

  • 如需其他事件欄位,請參閱 Amazon EventBridge 事件。

下列範例顯示因函式錯誤而導致處理失敗三次事件的呼叫記錄。呼叫記錄包含事件、回應以及記錄傳送原因的詳細資訊。

{ "version": "1.0", "timestamp": "2019-11-14T18:16:05.568Z", "requestContext": { "requestId": "e4b46cbf-b738-xmpl-8880-a18cdf61200e", "functionArn": "arn:aws:lambda:us-east-2:123456789012:function:my-function:$LATEST", "condition": "RetriesExhausted", "approximateInvokeCount": 3 }, "requestPayload": { "ORDER_IDS": [ "9e07af03-ce31-4ff3-xmpl-36dce652cb4f", "637de236-e7b2-464e-xmpl-baf57f86bb53", "a81ddca6-2c35-45c7-xmpl-c3a03a31ed15" ] }, "responseContext": { "statusCode": 200, "executedVersion": "$LATEST", "functionError": "Unhandled" }, "responsePayload": { "errorMessage": "RequestId: e4b46cbf-b738-xmpl-8880-a18cdf61200e Process exited before completing request" } }

下列步驟說明如何使用 Lambda 主控台設定函數的目的地。

設定非同步調用記錄的目的地
  1. 開啟 Lambda 主控台中的 函數頁面

  2. 選擇一個函數。

  3. 函數概觀 下,選擇 新增目的地

  4. 針對 來源,選擇 非同步調用

  5. 如為條件,請從下列選項中選擇:

    • On failure (失敗時) - 當事件的所有處理嘗試都失敗,或超過存留期上限時,傳送記錄。

    • 成功時 - 當函數成功處理非同步調用時傳送記錄。

  6. 對於 目的地類型,請選擇接收調用記錄的資源類型。

  7. 對於 目的地,請選擇一個資源。

  8. 選擇 儲存

當調用與條件相符時,Lambda 會將包含調用之詳細資訊的 JSON 文件傳送到目的地。

目的地特定 JSON 格式
  • 對於 Amazon SQS 和 Amazon SNS (SnsDestinationSqsDestination),調用記錄會以 Message 形式傳遞到目的地。

  • 對於 Lambda(LambdaDestination),調用記錄會以承載形式傳遞給函數。

  • For EventBridge (EventBridgeDestination),PutEvents呼叫記錄會以呼叫detail中的方式傳遞。source 事件欄位的值是 lambdadetail-type 事件欄位的值是 Lambda Function Invocation Result – Success (Lambda 函數調用結果 – 成功) 或 Lambda Function Invocation Result – Failure (Lambda 函數調用結果 – 失敗)。resource 事件欄位包含函數和目的地 Amazon Resource Names (ARN)。如需其他事件欄位,請參閱 Amazon EventBridge 事件。

下列範例顯示因函式錯誤而導致處理失敗三次事件的呼叫記錄。

範例 呼叫記錄
{ "version": "1.0", "timestamp": "2019-11-14T18:16:05.568Z", "requestContext": { "requestId": "e4b46cbf-b738-xmpl-8880-a18cdf61200e", "functionArn": "arn:aws:lambda:us-east-2:123456789012:function:my-function:$LATEST", "condition": "RetriesExhausted", "approximateInvokeCount": 3 }, "requestPayload": { "ORDER_IDS": [ "9e07af03-ce31-4ff3-xmpl-36dce652cb4f", "637de236-e7b2-464e-xmpl-baf57f86bb53", "a81ddca6-2c35-45c7-xmpl-c3a03a31ed15" ] }, "responseContext": { "statusCode": 200, "executedVersion": "$LATEST", "functionError": "Unhandled" }, "responsePayload": { "errorMessage": "RequestId: e4b46cbf-b738-xmpl-8880-a18cdf61200e Process exited before completing request" } }

呼叫記錄包含事件、回應以及記錄傳送原因的詳細資訊。

追蹤傳至目的地的請求

您可以使用 AWS X-Ray 查看每個請求排入佇列、由 Lambda 函數處理並傳遞至目的地服務的連接檢視。為調用函數的函數或服務啟用 X-Ray 追蹤時,Lambda 會將 X-Ray 標頭新增至請求,並將標頭傳送至目的地服務。來自上游服務的追蹤會自動連結至來自下游 Lambda 函數和目標服務的追蹤,以建立整個應用程式的 end-to-end 檢視。如需追蹤的詳細資訊,請參閱:使用視覺化 Lambda 函數叫用 AWS X-Ray

非同步調用組態 API

若要使用 AWS CLI 或 AWS SDK 管理非同步叫用設定,請使用下列 API 作業。

若要使用配置非同步呼叫 AWS CLI,請使用指put-function-event-invoke-config令。下列範例會設定事件存留期為 1 小時且不重試的函數。

aws lambda put-function-event-invoke-config --function-name error \ --maximum-event-age-in-seconds 3600 --maximum-retry-attempts 0

您應該會看到下列輸出:

{ "LastModified": 1573686021.479, "FunctionArn": "arn:aws:lambda:us-east-2:123456789012:function:error:$LATEST", "MaximumRetryAttempts": 0, "MaximumEventAgeInSeconds": 3600, "DestinationConfig": { "OnSuccess": {}, "OnFailure": {} } }

put-function-event-invoke-config 命令會覆寫任何在函數、版本或別名上的現有組態。若要設定選項而不重設其他項目,請使用 update-function-event-invoke-config。下列範例會將 Lambda 設定為在無法處理事件時,將記錄傳送至名為 destination 的標準 SQS 佇列。

aws lambda update-function-event-invoke-config --function-name error \ --destination-config '{"OnFailure":{"Destination": "arn:aws:sqs:us-east-2:123456789012:destination"}}'

您應該會看到下列輸出:

{ "LastModified": 1573687896.493, "FunctionArn": "arn:aws:lambda:us-east-2:123456789012:function:error:$LATEST", "MaximumRetryAttempts": 0, "MaximumEventAgeInSeconds": 3600, "DestinationConfig": { "OnSuccess": {}, "OnFailure": { "Destination": "arn:aws:sqs:us-east-2:123456789012:destination" } } }

無效字母佇列

做為失敗目標的替代項目,您可以設定您的函數,使其具備一個無效字母佇列來儲存捨棄的事件,以供後續處理。無效字母佇列的運作方式與失敗目標相同,會在事件的所有處理嘗試失敗,或是在沒有處理的情況下過期時使用。但是,無效字母佇列是函數版本特定組態的一部分,因此會在您發佈版本時鎖定。失敗目標也支援其他目標,並會在呼叫記錄中包含函數回應的詳細資訊。

若要重新處理無效字母佇列中的事件,請將它設定為 Lambda 函數的事件來源。或者,您可以手動擷取事件。

您可以為無效字母佇列選擇 Amazon SQS 標準佇列或 Amazon SNS 標準主題。不支援 SQS FIFO 佇列和 Amazon SNS FIFO 主題。如果您沒有佇列或主題,請加以建立。選擇符合您的使用案例的目標類型。

若要將事件傳送到佇列或主題,您的函式需要額外許可。將具有所需許可的政策新增到您函式的執行角色

如果目標佇列或主題使用客戶受管金鑰加密,則執行角色也必須是金鑰以資源為基礎政策中的使用者。

在建立目標及更新函式的執行角色之後,將無效字母佇列新增到您的函式。您可以設定多個函式來將事件傳送到相同的目標。

設定無效字母佇列
  1. 開啟 Lambda 主控台中的 函數頁面

  2. 選擇一個函數。

  3. 選擇 組態,然後選擇 非同步調用

  4. 非同步調用 下方,選擇 編輯

  5. DLQ 資源設定為 Amazon SQSAmazon SNS

  6. 選擇目標佇列或主題。

  7. 選擇 儲存

若要使用配置無效字母佇列 AWS CLI,請使用指update-function-configuration令。

aws lambda update-function-configuration --function-name my-function \ --dead-letter-config TargetArn=arn:aws:sns:us-east-2:123456789012:my-topic

Lambda 會依現狀將事件傳送到無效字母佇列,其屬性中有額外資訊。您可以使用此資訊來識別該函式所傳回的錯誤,或建立事件與日誌或 AWS X-Ray 追蹤的關聯性。

無效字母佇列訊息屬性
  • RequestID (字串) - 調用請求的 ID。請求 ID 會出現於函式日誌中。您也可以使用 X-Ray SDK 在追蹤的屬性中記錄請求 ID。然後,您可以在 X-Ray 主控台中依請求 ID 搜尋追蹤。

  • ErrorCode(數字) — HTTP 狀態碼。

  • ErrorMessage(字串) — 錯誤訊息的前 1 KB。

Amazon SQS 主控台中無效字母佇列的事件屬性。

如果 Lambda 無法將訊息傳送至無效字母佇列,就會刪除事件並發出錯誤量度。DeadLetter這可能由於缺乏許可,或訊息總大小超過目標佇列或主題的限制,而發生此狀況。例如,假設本文大小接近 256 KB 的 Amazon SNS 通知會觸發導致錯誤的函數。在這種情況下,Amazon SNS 新增的事件資料與 Lambda 新增的屬性結合後,可能導致訊息超過無效字母佇列中允許的大小上限。

如果您使用 Amazon SQS 作為事件來源,請對 Amazon SQS 佇列本身 (而非 Lambda 函數) 設定無效字母佇列。如需更多詳細資訊,請參閱 搭配 Amazon SQS 使用 Lambda