Step Functions 中的錯誤處理 - AWS Step Functions

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

Step Functions 中的錯誤處理

除了Pass和狀態之外的所有Wait狀態都可能會遇到執行階段錯誤。錯誤可能由於各種原因而發生,例如以下示例:

  • 狀態機器定義問題 (例如,Choice 狀態中沒有相符的規則)

  • 任務失敗 (例如,AWS Lambda 函數中的例外狀況)

  • 暫時性問題 (例如,網路分割區事件)

根據預設,當狀態回報錯誤時,AWS Step Functions 會導致完全無法執行。

提示

若要部署包含錯誤處理的工作流程範例AWS 帳戶,請參閱單元 8-AWS Step Functions工作坊的錯誤處理

錯誤名稱

Step Functions 使用區分大小寫的字串 (稱為錯誤名稱) 識別 Amazon 州語言中的錯誤。Amazon States 語言會定義一組內建字串,這些字串命名為已知錯誤,全部都以前置States.詞開頭。

States.ALL

符合任何已知錯誤名稱的萬用字元。

注意

此錯誤類型無法 catch States.DataLimitExceeded 終端錯誤類型和運行時錯誤類型。如需這些錯誤類型的詳細資訊,請參閱States.DataLimitExceededStates.Runtime

States.DataLimitExceeded

「Step Functions」會在下列情況下報告States.DataLimitExceeded例外:

  • 當連接器的輸出大於有效負載大小配額時。

  • 當狀態的輸出大於有效負載大小配額時。

  • Parameters處理之後,狀態的輸入大於有效負載大小配額時。

如需配額的詳細資訊,請參閱配額

注意

這是錯誤類型無法捕獲的終端States.ALL錯誤。

States.ExceedToleratedFailureThreshold

Map狀態失敗,因為失敗的項目數超過狀態機器定義中指定的臨界值。如需詳細資訊,請參閱分散式對應狀態的容許失敗臨界值

States.HeartbeatTimeout

Task態無法傳送活動訊號超過該HeartbeatSeconds值的時間。

注意

此錯誤僅在CatchRetry欄位中可用。

States.IntrinsicFailure

嘗試在有效負載範本中叫用內建函式失敗。

States.ItemReaderFailed

Map態失敗,因為無法從ItemReader欄位中指定的項目來源讀取。如需詳細資訊,請參閱ItemReader

States.NoChoiceMatched

Choice狀態無法將輸入與「選擇規則」中定義的條件相符,且未指定「預設」轉移。

States.ParameterPathFailure

嘗試取代狀態欄位中名稱以.$使用路徑結尾的Parameters欄位失敗。

States.Permissions

Task狀態失敗,因為它沒有足夠的權限來運行指定的代碼。

States.ResultPathMatchFailure

Step Functions 無法將狀態的ResultPath字段應用於輸入接收到的狀態。

States.ResultWriterFailed

Map態失敗,因為無法將結果寫入ResultWriter欄位中指定的目的地。如需詳細資訊,請參閱ResultWriter

States.Runtime

由於某些無法處理的例外狀況,執行失敗。這些通常是在運行時間的錯誤所導致,例如嘗試在 Null JSON 承載上套用 InputPathOutputPathStates.Runtime錯誤無法重新擷取,而且永遠會導致執行失敗。重試或 catch States.ALL 獲不會 catch 獲States.Runtime錯誤。

States.TaskFailed

在執行期間失敗的 Task 狀態。在重試或 catch 中使用時,States.TaskFailed充當通配符,匹配除了任何已知的錯誤名稱States.Timeout

States.Timeout

執行時間超過 TimeoutSeconds 值,或無法傳送活動訊號的時間超過 HeartbeatSeconds 值的 Task 狀態。

此外,如果狀態機器的執行時間超過指定TimeoutSeconds值,則執行會失敗並顯示States.Timeout錯誤。

狀態可以回報具有其他名稱的錯誤。但是,這些錯誤名稱不能以States.前綴開頭。

為確保最佳實務,請確認生產程式碼可以處理 AWS Lambda 服務例外狀況 (Lambda.ServiceExceptionLambda.SdkClientException)。如需詳細資訊,請參閱處理 Lambda 務例外

注意

Lambda 中未處理的錯誤會報告為錯誤輸出Lambda.Unknown中。這些包括 out-of-memory 錯誤和功能超時。您可以在Lambda.UnknownStates.ALL、或上進行比對States.TaskFailed來處理這些錯誤。當 Lambda 達到調用的最大數量時,錯誤為。Lambda.TooManyRequestsException如需 Lambda 函數錯誤的詳細資訊,請參閱AWS Lambda開發人員指南中的錯誤處理和自動重試

發生錯誤後重試

TaskParallel、和Map狀態可以有一個名為的欄位Retry,其值必須是稱為擷取器的物件陣列。個別的 Retrier 代表特定的重試次數,通常為較長的時間間隔。

當其中一個狀態報告錯誤且有Retry欄位時,Step Functions 會依陣列中列出的順序掃描擷取器。當錯誤名稱出現在檢索器欄位的值中時,狀態機會按照ErrorEquals欄位中的定義進行重試嘗試。Retry

如果您的redriven執行重新執行已定義重試次數的任務平行、或 Inline Map 狀態,則這些狀態的重試嘗試次數會重設為 0,以允許嘗試次數上限。redrive對於redriven執行,您可以使用主控台追蹤這些狀態的個別重試嘗試。如需詳細資訊,請參閱 Redriving處決 中的 redriven執行的重試行為

Retrier 包含下列欄位:

注意

重試被視為狀態轉換。有關狀態轉換如何影響計費的詳細資訊,請參閱 Step Functions 定價

ErrorEquals (必要)

符合錯誤名稱的非空白字串陣列。當狀態報告錯誤時,Step Functions 會透過擷取器進行掃描。當錯誤名稱出現於此陣列時,它會實作此 Retrier 中所述的重試政策。

IntervalSeconds (選用)

正整數;代表第一次嘗試重試前的秒數 (1預設情況下)。 IntervalSeconds其最大值為 99999999。

MaxAttempts (選用)

正整數,其代表重試次數上限 (預設值 3)。如果出現錯誤的次數超過指定次數,則重試會停止且一般錯誤處理會繼續執行。值0指定永遠不會重試錯誤。 MaxAttempts其最大值為 99999999。

BackoffRate (選用)

每次重試嘗試後,表示重試間隔的乘數IntervalSeconds會增加。依預設,BackoffRate值會增加2.0

例如,假設你IntervalSeconds是 3,MaxAttempts是 3,BackoffRate是 2。第一次重試嘗試會在錯誤發生後三秒鐘進行。第二次重試會在第一次嘗試重試後六秒進行。第三次重試會在第二次重試嘗試後 12 秒進行。

MaxDelaySeconds (選用)

正整數;設定重試間隔可以增加的最大值 (以秒為單位)。此欄位對於欄位搭配使用很有幫助。BackoffRate您在此欄位中指定的值會限制套用至每次連續重試嘗試的輪詢率乘數所產生的指數等待時間。您必須指定一個大於 0 且小於 31622401 的值。MaxDelaySeconds

如果未指定此值,Step Functions 不會限制重試嘗試之間的等待時間。

JitterStrategy (選用)

字串,決定是否要在連續重試嘗試之間的等待時間中包含抖動。抖動會在隨機延遲間隔內分散這些嘗試,以減少同時重試的次數。該字符串接受FULLNONE作為其值。預設值為 NONE

例如,假設您已設定MaxAttempts為 3、IntervalSeconds為 2,並設定BackoffRate為 2。第一次重試嘗試會在錯誤發生後兩秒鐘進行。第二次重試會在第一次重試嘗試後四秒進行,第三次重試會在第二次重試嘗試後 8 秒進行。如果設定JitterStrategyFULL,則第一個重試間隔會在 0 到 2 秒之間隨機排列,第二個重試間隔會在 0 到 4 秒之間隨機排列,第三個重試間隔會在 0 到 8 秒之間隨機排列。

重試欄位範例

本節包含下列Retry欄位範例。

提示

若要將錯誤處理工作流程的範例部署到您的AWS 帳戶,請參閱AWS Step Functions工作坊錯誤處理模組。

範例 1 — 重試 BackoffRate

下列的範例會在等待三秒鐘後進行兩次重試嘗試,而第一次重試則會進行。Retry根據BackoffRate您指定的,「Step Functions 數」會增加每次重試之間的間隔,直到達到重試嘗試次數上限為止。在下列範例中,第二次重試嘗試會在第一次重試後等待三秒鐘後開始。

"Retry": [ { "ErrorEquals": [ "States.Timeout" ], "IntervalSeconds": 3, "MaxAttempts": 2, "BackoffRate": 1 } ]
範例 2 — 重試 MaxDelaySeconds

下列範例會進行三次重試,並限制 5 秒後產生的BackoffRate等待時間。第一次重試會在等待三秒鐘後進行。第二次和第三次重試嘗試會在前一次重試嘗試後等待五秒鐘後發生,因為等待時間上限是由設定的最大等待時間限制MaxDelaySeconds

"Retry": [ { "ErrorEquals": [ "States.Timeout" ], "IntervalSeconds": 3, "MaxAttempts": 3, "BackoffRate":2, "MaxDelaySeconds": 5, "JitterStrategy": "FULL" } ]

如果沒有MaxDelaySeconds,則第二次重試會在第一次重試後六秒進行,第三次重試會在第二次重試後 12 秒進行。

範例 3 — 重試除狀態之外的所有錯誤。逾時

出現在 Retrier 的 ErrorEquals 欄位中的預留名稱 States.ALL 是符合任何錯誤名稱的萬用字元。它必須單獨顯示在 ErrorEquals 陣列中,而且必須顯示在 Retry 陣列的最後一個 Retrier 中。該名稱States.TaskFailed還具有通配符,並匹配除外的任何錯誤States.Timeout

下列Retry欄位範例會重試除外States.Timeout的任何錯誤。

"Retry": [ { "ErrorEquals": [ "States.Timeout" ], "MaxAttempts": 0 }, { "ErrorEquals": [ "States.ALL" ] } ]
範例 4 — 複雜的重試案例

Retrier 的參數會套用於在單一狀態執行的範疇中對 Retrier 的所有造訪。

請考慮以下 Task 狀態。

"X": { "Type": "Task", "Resource": "arn:aws:states:us-east-1:123456789012:task:X", "Next": "Y", "Retry": [ { "ErrorEquals": [ "ErrorA", "ErrorB" ], "IntervalSeconds": 1, "BackoffRate": 2.0, "MaxAttempts": 2 }, { "ErrorEquals": [ "ErrorC" ], "IntervalSeconds": 5 } ], "Catch": [ { "ErrorEquals": [ "States.ALL" ], "Next": "Z" } ] }

此工作連續失敗四次,輸出以下錯誤名稱:ErrorAErrorBErrorC、和ErrorB。因此會發生下列情況:

  • 前兩個錯誤匹配第一個檢索器,並導致等待一秒和兩秒。

  • 第三個錯誤匹配第二個檢索器,並導致等待五秒鐘。

  • 第四個錯誤也匹配第一個檢索器。但是,對於該特定錯誤,它已經達到了兩次 retry(MaxAttempts)的最大值。因此,該擷取器會失敗,而且執行會透過Catch欄位將工作流程重新導向至Z狀態。

后援国家

TaskMapParallel狀態每個狀態都可以有一個名為的欄位Catch。此欄位的值必須物件陣列,也稱為 Catcher

Catcher 包含下列欄位。

ErrorEquals (必要)

符合錯誤名稱的非空白字串陣列,其指定方式完全與同名的 Retrier 欄位一樣。

Next (必要)

字串,該字串必須完全符合其中一個狀態機器的狀態名稱。

ResultPath (選用)

捕捉器傳送到Next欄位中指定狀態的輸入的路徑。

當狀態報告錯誤且沒有Retry欄位,或者如果重試無法解決錯誤,Step Functions 會依陣列中列出的順序掃描擷取器。當錯誤名稱顯示於 Catcher 的 ErrorEquals 欄位值時,狀態機器會轉換到 Next 欄位中具名的狀態。

出現在 Catcher 的 ErrorEquals 欄位中的預留名稱 States.ALL 是符合任何錯誤名稱的萬用字元。它必須單獨顯示在 ErrorEquals 陣列中,而且必須顯示在 Catch 陣列的最後一個 Catcher 中。該名稱States.TaskFailed還具有通配符,並匹配除外的任何錯誤States.Timeout

下列Catch欄位範例會轉換至 Lambda 函數輸出未處理的 Java 例外狀況RecoveryState時命名的狀態。否則,此欄位會轉換到 EndState 狀態。

"Catch": [ { "ErrorEquals": [ "java.lang.Exception" ], "ResultPath": "$.error-info", "Next": "RecoveryState" }, { "ErrorEquals": [ "States.ALL" ], "Next": "EndState" } ]
注意

每個 Catcher 可以指定多個要處理的錯誤。

錯誤輸出

當 Step Functions 轉換到 catch 名稱中指定的狀態時,該對象通常包含該字段Cause。此欄位的值是人類可讀的錯誤描述。此物件也稱為「錯誤輸出」

在這個範例中,第一個 Catcher 包含 ResultPath 欄位。其運作方式類似於狀態最上層中的 ResultPath 欄位,會造成兩種可能性:

  • 它會取得該狀態執行的結果,並覆寫狀態輸入的全部或部分。

  • 它會取得結果,並將結果新增至輸入。在捕手處理錯誤的情況下,狀態的執行結果是錯誤輸出。

因此,對於示例中的第一個捕獲器,捕手將錯誤輸出添加到輸入中,error-info如果輸入中還沒有具有此名稱的字段,則命名為的字段。然後,捕手將整個輸入發送到RecoveryState。對於第二個捕獲器,錯誤輸出覆蓋輸入,捕手僅將錯誤輸出發送到。EndState

注意

如未指定 ResultPath 欄位,它會預設為 $,該值會選取並覆寫整個輸入。

當一個狀態同時具有RetryCatch字段時,Step Functions 首先使用任何適當的檢索器。如果重試原則無法解決錯誤,「Step Functions」會套用相符的捕捉器轉換。

原因有效載荷和服務整合

捕手返回一個字符串有效載荷作為輸出。使用 Amazon Athena 等服務整合時AWS CodeBuild,您可能需要將Cause字串轉換為 JSON。以下具有內在函數的Pass狀態示例顯示瞭如何將Cause字符串轉換為 JSON。

"Handle escaped JSON with JSONtoString": { "Type": "Pass", "Parameters": { "Cause.$": "States.StringToJson($.Cause)" }, "Next": "Pass State with Pass Processing" },

使用重試和使用 Catch 的狀態機器示例

以下範例中定義的狀態機器假設存在兩個 Lambda 函數:一個永遠失敗,另一個等待足夠長的時間以允許狀態機器中定義的逾時發生。

這是一個 Node.js Lambda 函數的定義,該函數總是失敗,並返回消息error。在接下來的狀態機器範例中,會命名此 Lambda 函數FailFunction。如需建立 Lambda 函數的相關資訊,請參閱一步驟 1:建立 Lambda 函數節。

exports.handler = (event, context, callback) => { callback("error"); };

這是一個 Node.js Lambda 函數的定義,睡眠 10 秒。在接下來的狀態機器範例中,會命名此 Lambda 函數sleep10

注意

在 Lambda 主控台中建立此 Lambda 函數時,請記得將 [進階設定] 區段中的時值從 3 秒 (預設值) 變更為 11 秒。

exports.handler = (event, context, callback) => { setTimeout(function(){ }, 11000); };

使用「重試」處理失敗

此狀態機器會使用 Retry 欄位來重試失敗且輸出錯誤名稱 HandledError 的函數。它重試此函數兩次,並在重試之間進行指數輪詢。

{ "Comment": "A Hello World example of the Amazon States Language using an AWS Lambda function", "StartAt": "HelloWorld", "States": { "HelloWorld": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:FailFunction", "Retry": [ { "ErrorEquals": ["HandledError"], "IntervalSeconds": 1, "MaxAttempts": 2, "BackoffRate": 2.0 } ], "End": true } } }

此變體使用預先定義的錯誤代碼States.TaskFailed,該代碼與 Lambda 函數輸出的任何錯誤匹配。

{ "Comment": "A Hello World example of the Amazon States Language using an AWS Lambda function", "StartAt": "HelloWorld", "States": { "HelloWorld": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:FailFunction", "Retry": [ { "ErrorEquals": ["States.TaskFailed"], "IntervalSeconds": 1, "MaxAttempts": 2, "BackoffRate": 2.0 } ], "End": true } } }
注意

最佳實務是,參考 Lambda 函數的工作應該處理 Lambda 服務例外狀況。如需詳細資訊,請參閱處理 Lambda 務例外

使用 Catch 處理失敗

此範例會使用 Catch 欄位。當 Lambda 函數輸出錯誤時,它會捕獲錯誤,並且狀態機轉換為狀fallback態。

{ "Comment": "A Hello World example of the Amazon States Language using an AWS Lambda function", "StartAt": "HelloWorld", "States": { "HelloWorld": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:FailFunction", "Catch": [ { "ErrorEquals": ["HandledError"], "Next": "fallback" } ], "End": true }, "fallback": { "Type": "Pass", "Result": "Hello, AWS Step Functions!", "End": true } } }

此變體使用預先定義的錯誤代碼States.TaskFailed,該代碼與 Lambda 函數輸出的任何錯誤匹配。

{ "Comment": "A Hello World example of the Amazon States Language using an AWS Lambda function", "StartAt": "HelloWorld", "States": { "HelloWorld": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:FailFunction", "Catch": [ { "ErrorEquals": ["States.TaskFailed"], "Next": "fallback" } ], "End": true }, "fallback": { "Type": "Pass", "Result": "Hello, AWS Step Functions!", "End": true } } }

使用「重試」處理逾時

此狀態機器使用Retry欄位重試逾時的Task狀態,根據中TimeoutSeconds所指定的逾時值。Step Functions 數會在此Task狀態下重試 Lambda 函數叫用兩次,並在重試之間進行指數輪詢。

{ "Comment": "A Hello World example of the Amazon States Language using an AWS Lambda function", "StartAt": "HelloWorld", "States": { "HelloWorld": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:sleep10", "TimeoutSeconds": 2, "Retry": [ { "ErrorEquals": ["States.Timeout"], "IntervalSeconds": 1, "MaxAttempts": 2, "BackoffRate": 2.0 } ], "End": true } } }

使用 Catch 處理超時

此範例會使用 Catch 欄位。如果發生逾時,狀態機器就會轉換到 fallback 狀態。

{ "Comment": "A Hello World example of the Amazon States Language using an AWS Lambda function", "StartAt": "HelloWorld", "States": { "HelloWorld": { "Type": "Task", "Resource": "arn:aws:lambda:us-east-1:123456789012:function:sleep10", "TimeoutSeconds": 2, "Catch": [ { "ErrorEquals": ["States.Timeout"], "Next": "fallback" } ], "End": true }, "fallback": { "Type": "Pass", "Result": "Hello, AWS Step Functions!", "End": true } } }
注意

您可以使用 ResultPath 來保留狀態輸入與錯誤。請參閱用於 ResultPath 將錯誤和輸入都包含在 Catch