非同步叫用 - AWS Lambda

非同步叫用

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

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 CLI config 檔案中設定此選項。

{ "StatusCode": 202 }

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

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

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

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

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

您也可以設定 Lambda,將叫用記錄傳送到另一個服務。Lambda 支持以下目的地以進行非同步呼用。

  • Amazon SQS - 標準 SQS 佇列。

  • Amazon SNS - SNS 主題。

  • AWS Lambda - Lambda 函數。

  • Amazon EventBridge - EventBridge 事件匯流排。

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

注意

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

設定非同步呼叫的錯誤處理

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

設定錯誤處理

  1. 開啟 Lambda 主控台中的 Functions (函數) 頁面

  2. 選擇一個函數。

  3. 選擇 Configuration (組態),然後選擇 Asynchronous invocation (非同步叫用)

  4. Asynchronous invocation (非同步呼叫) 下方,選擇 Edit (編輯)

  5. 進行下列設定。

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

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

  6. 選擇 Save (儲存)。

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

設定非同步叫用的目的地

若要將非同步呼叫的記錄傳送至另一個服務,請將目的地新增至您的函數。您可以為處理失敗的事件和處理成功的事件設定不同目的地。與錯誤處理設定相似,您可以設定函數、版本或是別名的目標。

下列範例顯示正在處理非同步呼叫的函式。當函數傳回一個成功的回應或退出而不擲出錯誤時,Lambda 會傳送叫用的記錄到 Eventbridge 事件匯流排。當事件的所有處理嘗試失敗時,Lambda 會將叫用記錄傳送至 Amazon SQS 佇列。


        視結果而定,Lambda 會將呼叫記錄傳送至佇列或事件匯流排目的地。

若要將事件傳送到目的地,您的函數需要額外許可。將具有所需許可的政策新增到您函式的執行角色。每個目的地服務都需要不同的權限,如下所示:

在 Lambda 主控台的函數視覺化中,將目的地新增至您的函數。

設定非同步呼叫記錄的目的地

  1. 開啟 Lambda 主控台中的 Functions (函數) 頁面

  2. 選擇一個函數。

  3. Function overview (函數概觀) 下,選擇 Add destination (新增目的地)

  4. 針對 Source (來源),選擇 Asynchronous invocation (非同步呼叫)

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

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

    • On success (成功時) - 當函數成功處理非同步叫用時傳送記錄。

  6. 對於 Destination type (目的地類型),請選擇接收叫用記錄的資源類型。

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

  8. 選擇 Save (儲存)。

當叫用與條件相符時,Lambda 會將包含叫用之詳細資訊的 JSON 文件傳送到目的地。下列範例顯示因函式錯誤而導致處理失敗三次事件的呼叫記錄。

範例 呼叫記錄

{ "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" } }

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

非同步呼叫組態 API

若要使用 AWS CLI 或 AWS 開發套件來管理非同步叫用設定,請使用下列 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 主題。如果您沒有佇列或主題,請加以建立。選擇符合您的使用案例的目標類型。

  • Amazon SQS 佇列 - 佇列會保留失敗的事件,直到其遭到擷取為止。如果您希望單一實體 (例如 Lambda 函數或 CloudWatch 警示) 處理失敗的事件,請選擇 Amazon SQS 佇列。如需更多詳細資訊,請參閱 搭配 Amazon SQS 使用 Lambda

    Amazon SQS 主控台中建立佇列。

  • Amazon SNS 主題 - 主題會將失敗的事件轉送到一個或多個目的地。如果您希望多個實體對失敗的事件採取動作,請選擇 Amazon SNS 主題。例如,您可以設定一個主題,以將事件傳送到電子郵件地址、Lambda 函數及/或 HTTP 端點。如需更多詳細資訊,請參閱 搭配使用 AWS Lambda 與 Amazon SNS

    Amazon SNS 主控台中建立主題。

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

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

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

設定無效信件佇列

  1. 開啟 Lambda 主控台中的 Functions (函數) 頁面

  2. 選擇一個函數。

  3. 選擇 Configuration (組態),然後選擇 Asynchronous invocation (非同步叫用)

  4. Asynchronous invocation (非同步呼叫) 下方,選擇 Edit (編輯)

  5. DLQ 資源設定為 Amazon SQSAmazon SNS

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

  7. 選擇 Save (儲存)。

若要透過 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 無法將訊息傳送到無效字母佇列,則會刪除事件並發出 DeadLetterErrors 指標。這可能由於缺乏許可,或訊息總大小超過目標佇列或主題的限制,而發生此狀況。例如,如果內文接近 256 KB 的 Amazon SNS 通知觸發一個造成錯誤的函數,則 Amazon SNS 新增的額外事件資料與 Lambda 新增的屬性結合後,可能導致訊息超過無效字母佇列中允許的大小上限。

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