View a markdown version of this page

重試 Lambda 耐用函數 - AWS Lambda

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

重試 Lambda 耐用函數

耐用的 函數提供自動重試功能,讓您的應用程式能夠適應暫時性故障。開發套件處理兩個層級的重試:商業邏輯故障的步驟重試,以及基礎設施故障的後端重試。

步驟重試

當步驟中發生未攔截的例外狀況時,軟體開發套件會根據設定的重試策略自動重試步驟。步驟重試是檢查點操作,可讓 SDK 暫停執行並在稍後繼續,而不會遺失進度。

步驟重試行為

下表說明 SDK 在步驟中如何處理例外狀況:

案例 會發生什麼情況 計量影響
步驟中剩餘重試嘗試的例外狀況 SDK 會建立重試的檢查點,並暫停函數。在下一次調用時,步驟會重試已設定的退避延遲。 1 個操作 + 錯誤承載大小
步驟 中沒有剩餘重試嘗試的例外狀況 步驟失敗並擲回例外狀況。如果您的處理常式程式碼未擷取此例外狀況,則整個執行會失敗。 1 個操作 + 錯誤承載大小

當步驟需要重試時,開發套件會檢查重試狀態,並在沒有其他工作執行時結束 Lambda 調用。這可讓 SDK 實作退避延遲,而不會耗用運算資源。函數會在退避期間後自動恢復。

設定步驟重試策略

設定重試策略以控制步驟處理失敗的方式。您可以指定重試的嘗試次數上限、退避間隔和條件。

最大嘗試次數的指數退避:

TypeScript
const result = await context.step('call-api', async () => { const response = await fetch('https://api.example.com/data'); if (!response.ok) throw new Error(`API error: ${response.status}`); return await response.json(); }, { retryStrategy: (error, attemptCount) => { if (attemptCount >= 5) { return { shouldRetry: false }; } // Exponential backoff: 2s, 4s, 8s, 16s, 32s (capped at 300s) const delay = Math.min(2 * Math.pow(2, attemptCount - 1), 300); return { shouldRetry: true, delay: { seconds: delay } }; } });
Python
def retry_strategy(error, attempt_count): if attempt_count >= 5: return RetryDecision(should_retry=False) # Exponential backoff: 2s, 4s, 8s, 16s, 32s (capped at 300s) delay = min(2 * (2 ** (attempt_count - 1)), 300) return RetryDecision(should_retry=True, delay=delay) result = context.step( lambda _: call_external_api(), name='call-api', config=StepConfig(retry_strategy=retry_strategy) )

固定間隔退避:

TypeScript
const orders = await context.step('query-orders', async () => { return await queryDatabase(event.userId); }, { retryStrategy: (error, attemptCount) => { if (attemptCount >= 3) { return { shouldRetry: false }; } return { shouldRetry: true, delay: { seconds: 5 } }; } });
Python
def retry_strategy(error, attempt_count): if attempt_count >= 3: return RetryDecision(should_retry=False) return RetryDecision(should_retry=True, delay=5) orders = context.step( lambda _: query_database(event['userId']), name='query-orders', config=StepConfig(retry_strategy=retry_strategy) )

條件式重試 (僅重試特定錯誤):

TypeScript
const result = await context.step('call-rate-limited-api', async () => { const response = await fetch('https://api.example.com/data'); if (response.status === 429) throw new Error('RATE_LIMIT'); if (response.status === 504) throw new Error('TIMEOUT'); if (!response.ok) throw new Error(`API_ERROR_${response.status}`); return await response.json(); }, { retryStrategy: (error, attemptCount) => { // Only retry rate limits and timeouts const isRetryable = error.message === 'RATE_LIMIT' || error.message === 'TIMEOUT'; if (!isRetryable || attemptCount >= 3) { return { shouldRetry: false }; } // Exponential backoff: 1s, 2s, 4s (capped at 30s) const delay = Math.min(Math.pow(2, attemptCount - 1), 30); return { shouldRetry: true, delay: { seconds: delay } }; } });
Python
def retry_strategy(error, attempt_count): # Only retry rate limits and timeouts is_retryable = str(error) in ['RATE_LIMIT', 'TIMEOUT'] if not is_retryable or attempt_count >= 3: return RetryDecision(should_retry=False) # Exponential backoff: 1s, 2s, 4s (capped at 30s) delay = min(2 ** (attempt_count - 1), 30) return RetryDecision(should_retry=True, delay=delay) result = context.step( lambda _: call_rate_limited_api(), name='call-rate-limited-api', config=StepConfig(retry_strategy=retry_strategy) )

停用重試:

TypeScript
const isDuplicate = await context.step('check-duplicate', async () => { return await checkIfOrderExists(event.orderId); }, { retryStrategy: () => ({ shouldRetry: false }) });
Python
is_duplicate = context.step( lambda _: check_if_order_exists(event['orderId']), name='check-duplicate', config=StepConfig( retry_strategy=lambda error, attempt: {'should_retry': False} ) )

當重試策略傳回 時shouldRetry: false,步驟會立即失敗,無需重試。將此用於不應重試的操作,例如等冪等性檢查或具有無法安全重複之副作用的操作。

步驟外部的例外狀況

當您的處理常式程式碼中發生未攔截的例外狀況,但在任何步驟之外,軟體開發套件會將執行標記為失敗。這可確保正確擷取和報告應用程式邏輯中的錯誤。

案例 會發生什麼情況 計量影響
任何步驟外處理常式程式碼的例外狀況 SDK 會將執行標記為 FAILED,並傳回錯誤。系統不會自動重試例外狀況。 錯誤承載大小

若要啟用易出錯程式碼的自動重試,請使用重試策略將其包裝在步驟中。步驟提供可設定退避的自動重試,而步驟外的程式碼會立即失敗。

叫用重試

根據嘗試叫用 Lambda 耐久函數的方式,叫用層級重試的處理方式會有所不同。下表說明不同的調用類型如何影響調用層級重試。

調用類型 會發生什麼情況
同步調用 在持久的函數執行期間,Lambda 不會在錯誤上自動重試調用。對調用失敗的重試將取決於同步調用的來源。例如,使用 AWS SDK,InternalFailure 和 ThrottlingException 預設會自動重試。
非同步調用 如果持久性函數執行失敗 (例如,它會輸入 FAILED、STOPPED 或 TIMED_OUT 狀態),Lambda 不會重試執行。這與標準 Lambda 函數不同,其中 Lambda 會在非同步調用失敗時重試函數。非同步調用MaximumRetryAttempts的設定不適用於持久性執行。如果您為函數設定無效字母佇列 (DLQ),Lambda 會將觸發事件傳送至 DLQ。
ESM (事件來源映射) Lambda 預設會重試整個批次,直到成功為止。針對串流來源 (DynamoDB 和 Kinesis),您可以設定函數傳回錯誤時 Lambda 重試的次數上限。請參閱事件來源映射批次處理。對於 Amazon SQS ESM,您可以在原始 Amazon SQS 佇列上透過 DLQ 設定重試次數上限。請參閱設定 Amazon SQS ESM。或者,您可以考慮函數層級的 DLQ,Lambda 會將失敗的觸發事件傳送至 DLQ。請參閱函數 DLQ。如果您有興趣接收失敗所有處理嘗試的事件記錄,或成功處理嘗試的事件記錄,您可以設定 ESM 的目的地。請參閱叫用非同步目的地
直接觸發 這取決於「觸發器」。例如,Lambda 會以非同步方式處理由 Amazon S3 事件通知觸發的函數。請參閱使用 Lambda 處理 Amazon SQS 事件通知。Lambda 會以非同步方式處理由 Amazon SNS 事件通知觸發的函數。請參閱使用 Amazon SNS 通知叫用 Lambda 函數。非同步調用重試行為在「非同步調用」資料表項目中高於 。如果 Amazon SNS 無法連接至 Lambda 或訊息遭到拒絕,Amazon SNS 會在數小時中以增加的間隔重試。如需詳細資訊,請參閱 Amazon SNS 常見問答集中的可靠性。API Gateway 會同步叫用 Lambda,並將真正的錯誤回應傳回給請求者。請參閱叫用重試。同步調用重試行為在「同步調用」資料表項目中高於 。如需詳細資訊,請參閱每個直接觸發

後端重試

當 Lambda 遇到基礎設施故障、執行時間錯誤,或開發套件無法與持久的執行服務通訊時,就會發生後端重試。Lambda 會自動重試這些失敗,以協助您的耐用函數從暫時性基礎設施問題中復原。

後端重試案例

當函數遇到下列情況時,Lambda 會自動重試函數:

  • 內部服務錯誤 - 當 Lambda 或耐久執行服務傳回 5xx 錯誤時,表示暫時服務問題。

  • 調節 - 當函數因並行限制或服務配額而調節時。

  • 逾時 - 當 SDK 在逾時期間內無法達到持久的執行服務時。

  • 沙盒初始化失敗 - 當 Lambda 無法初始化執行環境時。

  • 執行時間錯誤 - 當 Lambda 執行時間遇到函數程式碼以外的錯誤時,例如out-of-memory錯誤或程序當機。

  • 無效的檢查點字符錯誤 - 當檢查點字符不再有效時,通常是由於服務端狀態變更。

下表說明 SDK 如何處理這些案例:

案例 會發生什麼情況 計量影響
耐用處理常式外的執行時間錯誤 (OOM、逾時、當機) Lambda 會自動重試調用。開發套件會從最後一個檢查點重播,略過完成的步驟。 錯誤承載大小 + 每次重試 1 個操作
呼叫 / GetDurableExecutionState APIs時的服務錯誤 (5xx) CheckpointDurableExecution 或逾時 Lambda 會自動重試調用。開發套件會從最後一個檢查點重播。 錯誤承載大小 + 每次重試 1 個操作
呼叫 / GetDurableExecutionState APIs 時調節 (429) CheckpointDurableExecution 或無效的檢查點字符 Lambda 會使用指數退避自動重試調用。開發套件會從最後一個檢查點重播。 錯誤承載大小 + 每次重試 1 個操作
當 / GetDurableExecutionState APIs 時,用戶端錯誤 CheckpointDurableExecution (4xx,429 和無效的字符除外) SDK 會將執行標記為 FAILED。不會自動重試,因為錯誤表示永久問題。 錯誤承載大小

後端重試會使用指數退避並繼續,直到函數成功或達到執行逾時為止。在重播期間,開發套件會略過已完成的檢查點,並繼續從上次成功的操作執行,確保您的函數不會重新執行已完成的工作。

重試最佳實務

設定重試策略時,請遵循下列最佳實務:

  • 設定明確的重試策略 - 不要依賴生產環境中的預設重試行為。針對您的使用案例,使用適當的最大嘗試次數和退避間隔來設定明確的重試策略。

  • 使用條件式重試 - shouldRetry 實作邏輯僅重試暫時性錯誤 (速率限制、逾時),並在永久錯誤時快速失敗 (找不到驗證失敗)。

  • 設定適當的最大嘗試次數 - 彈性和執行時間之間的平衡。太多重試可能會延遲故障偵測,而太少會導致不必要的故障。

  • 使用指數退避 - 指數退避可減少下游服務的負載,並提高從暫時性故障復原的可能性。

  • 在步驟中包裝容易出錯的程式碼 - 無法自動重試步驟外部的程式碼。使用重試策略在步驟中包裝外部 API 呼叫、資料庫查詢和其他容易出錯的操作。

  • 監控重試指標 - 在 Amazon CloudWatch 中追蹤步驟重試操作和執行失敗,以識別模式並最佳化重試策略。