本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
處理 Step Functions 工作流程中的錯誤
除了 Pass
和 Wait
狀態之外,所有狀態都可能遇到執行時間錯誤。錯誤可能由於各種原因而發生,包括下列項目:
-
狀態機器定義問題 - 例如沒有相符規則的選擇狀態
-
任務失敗 - 例如 AWS Lambda 函數中的例外狀況
-
暫時性問題 - 例如網路分割區事件
當狀態報告錯誤時, AWS Step Functions 預設為整個狀態機器執行失敗。Step Functions 也有更進階的錯誤處理功能。您可以設定狀態機器來擷取錯誤、重試失敗狀態,以及正常實作錯誤處理通訊協定。
提示
若要部署包含錯誤處理之工作流程的範例,請參閱 AWS Step Functions 研討會中的錯誤處理
錯誤名稱
Step Functions 使用區分大小寫的字串來識別 Amazon States Language 中的錯誤,稱為錯誤名稱。Amazon States Language 會定義一組內建字串,命名已知的錯誤,所有錯誤都以 States.
字首開頭。
-
States.ALL
-
符合任何已知錯誤名稱的萬用字元。
注意
此錯誤類型無法擷取
States.DataLimitExceeded
終端機錯誤類型和執行時間錯誤類型。如需這些錯誤類型的詳細資訊,請參閱 States.DataLimitExceeded和 States.Runtime。 -
States.DataLimitExceeded
-
由於下列條件而報告:
-
當連接器的輸出大於承載大小配額時。
-
當狀態的輸出大於承載大小配額時。
-
當
Parameters
處理後,狀態的輸入大於承載大小配額時。
如需配額的詳細資訊,請參閱 Step Functions 服務配額。
注意
這是錯誤類型無法攔截的終端
States.ALL
錯誤。 -
States.ExceedToleratedFailureThreshold
Map
狀態失敗,因為失敗項目的數量超過狀態機器定義中指定的閾值。如需詳細資訊,請參閱在 Step Functions 中設定分散式映射狀態的失敗閾值。-
States.HeartbeatTimeout
-
Task
狀態無法在超過HeartbeatSeconds
值的期間內傳送活動訊號。注意
此錯誤僅適用於
Catch
和Retry
欄位。 -
States.Http.Socket
-
當 HTTP 任務大約在 60 秒後發生此錯誤。請參閱 與 HTTP 任務相關的配額。
-
States.IntrinsicFailure
-
此錯誤名稱會保留供日後使用。使用錯誤名稱報告內部函數處理
States.Runtime
錯誤。 States.ItemReaderFailed
Map
狀態失敗,因為無法從ItemReader
欄位中指定的項目來源讀取。如需詳細資訊,請參閱ItemReader (地圖)
。-
States.NoChoiceMatched
-
此錯誤名稱會保留供日後使用。如果沒有符合的選項,則會使用錯誤名稱回報
States.Runtime
錯誤。 -
States.ParameterPathFailure
-
此錯誤名稱會保留供日後使用。參數處理錯誤會以
States.Runtime
錯誤名稱回報。 -
States.Permissions
-
Task
狀態失敗,因為它沒有足夠的權限來執行指定的程式碼。 -
States.ResultPathMatchFailure
-
Step Functions 無法將狀態
ResultPath
的欄位套用至接收狀態的輸入。 States.ResultWriterFailed
Map
狀態失敗,因為它無法將結果寫入ResultWriter
欄位中指定的目的地。如需詳細資訊,請參閱ResultWriter (地圖)
。States.Runtime
-
由於某些無法處理的例外狀況,導致執行失敗。這些通常是在運行時間的錯誤所導致,例如嘗試在 Null JSON 承載上套用
InputPath
或OutputPath
。States.Runtime
錯誤無法重試,且一律會導致執行失敗。重試或截獲States.ALL
不會截獲States.Runtime
錯誤。 -
States.TaskFailed
-
在執行期間失敗的
Task
狀態。在重試或擷取中使用時,States.TaskFailed
充當萬用字元,符合 以外的任何已知錯誤名稱States.Timeout
。 -
States.Timeout
-
執行時間超過
TimeoutSeconds
值,或無法傳送活動訊號的時間超過HeartbeatSeconds
值的Task
狀態。此外,如果狀態機器執行的時間超過指定的
TimeoutSeconds
值,則執行會失敗並顯示States.Timeout
錯誤。
狀態可以回報具有其他名稱的錯誤。不過,這些錯誤名稱不能以 States.
字首開頭。
最佳實務是確保生產程式碼可以處理 AWS Lambda 服務例外狀況 (Lambda.ServiceException
和 Lambda.SdkClientException
)。如需詳細資訊,請參閱處理暫時性 Lambda 服務例外狀況。
注意
Lambda 中未處理的錯誤會在錯誤輸出Lambda.Unknown
中報告為 。這些包括out-of-memory錯誤和函數逾時。您可以在 Lambda.Unknown
、 States.ALL
或 上比對 States.TaskFailed
,以處理這些錯誤。當 Lambda 達到呼叫數量上限時,錯誤為 Lambda.TooManyRequestsException
。如需 Lambda Handled
和Unhandled
錯誤的詳細資訊,請參閱《 AWS Lambda 開發人員指南FunctionError
》中的 。
發生錯誤後重試
Task
、 Parallel
和 Map
狀態可以有一個名為 的欄位Retry
,其值必須是稱為重試器的物件陣列。個別的 Retrier 代表特定的重試次數,通常為較長的時間間隔。
當其中一個狀態報告錯誤且有 Retry
欄位時,Step Functions 會依陣列中列出的順序掃描重試器。當錯誤名稱出現在重試器ErrorEquals
欄位的值中時,狀態機器會依 Retry
欄位所定義進行重試嘗試。
如果您的redriven執行重新執行您已定義重試的 任務工作流程狀態、 平行工作流程狀態或內嵌映射狀態,則這些狀態的重試嘗試計數會重設為 0,以允許 上的最大嘗試次數redrive。對於redriven執行,您可以使用 主控台追蹤這些狀態的個別重試嘗試。如需詳細資訊,請參閱 在 Step Functions redrive中使用 重新啟動狀態機器執行 中的 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
(選用) -
此字串決定是否要在連續重試嘗試之間的等待時間內包含抖動。抖動透過在隨機延遲間隔中分散這些重試,以減少同時重試嘗試。此字串接受
FULL
或NONE
作為其值。預設值為NONE
。例如,假設您已
MaxAttempts
將 設定為 3、IntervalSeconds
將 設定為 2,並將BackoffRate
設定為 2。第一次重試嘗試會在錯誤發生後兩秒進行。第二次重試會在第一次重試嘗試的四秒後進行,而第三次重試會在第二次重試嘗試的八秒後進行。如果您JitterStrategy
將 設定為FULL
,則第一個重試間隔會隨機介於 0 到 2 秒之間,第二個重試間隔會隨機介於 0 到 4 秒之間,第三個重試間隔則會隨機介於 0 到 8 秒之間。
重試欄位範例
本節包含下列Retry
欄位範例。
範例 1 – 使用 BackoffRate 重試
下列範例Retry
會嘗試兩次重試,第一次重試會在等待三秒後進行。根據您BackoffRate
指定的 ,Step Functions 會增加每次重試之間的間隔,直到達到重試嘗試次數上限為止。在下列範例中,第二次重試嘗試會在第一次重試後等待三秒後開始。
"Retry": [ {
"ErrorEquals": [ "States.Timeout" ],
"IntervalSeconds": 3,
"MaxAttempts": 2,
"BackoffRate": 1
} ]
範例 2 – 使用 MaxDelaySeconds 重試
下列範例會進行三次重試嘗試,並將 產生的等待時間限制BackoffRate
在 5 秒。第一次重試會在等待三秒後進行。由於 設定的等待時間上限,第二次和第三次重試嘗試會在先前的重試嘗試後等待五秒後進行MaxDelaySeconds
。
"Retry": [ {
"ErrorEquals": [ "States.Timeout" ],
"IntervalSeconds": 3,
"MaxAttempts": 3,
"BackoffRate":2,
"MaxDelaySeconds": 5,
"JitterStrategy": "FULL"
} ]
如果沒有 MaxDelaySeconds
,第二次重試嘗試會在第一次重試的六秒後進行,而第三次重試嘗試會在第二次重試的 12 秒後進行。
範例 3 – 重試 States.Timeout 以外的所有錯誤
出現在 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:region
: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"
} ]
}
此任務會連續失敗四次,並輸出這些錯誤名稱:ErrorA
、ErrorC
、 ErrorB
和 ErrorB
。因此會發生下列情況:
-
前兩個錯誤符合第一個重試器,並導致等待一秒和兩秒。
-
第三個錯誤符合第二個重試器,並導致等待 5 秒。
-
第四個錯誤也符合第一個重試器。不過,已達該特定錯誤的兩次重試次數上限 (
MaxAttempts
)。因此,該重試器失敗,執行會透過Catch
欄位將工作流程重新導向至Z
狀態。
備用狀態
Task
、 Map
和 Parallel
狀態各自可以有一個名為 的欄位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
。
當 Lambda 函數輸出未處理的 Java 例外狀況RecoveryState
時,下列Catch
欄位範例會轉換為名為 的狀態。否則,此欄位會轉換到 EndState
狀態。
"Catch": [ {
"ErrorEquals": [ "java.lang.Exception" ],
"ResultPath": "$.error-info",
"Next": "RecoveryState"
}, {
"ErrorEquals": [ "States.ALL" ],
"Next": "EndState"
} ]
注意
每個 Catcher 可以指定多個要處理的錯誤。
錯誤輸出
當 Step Functions 轉換到擷取名稱中指定的狀態時,物件通常包含 欄位 Cause
。此欄位的值是人類可讀的錯誤描述。此物件也稱為「錯誤輸出」。
在這個範例中,第一個 Catcher 包含 ResultPath
欄位。其運作方式類似於狀態最上層中的 ResultPath
欄位,會造成兩種可能性:
-
它採用該狀態的執行結果,並覆寫狀態輸入的全部或一部分。
-
它會取得結果,並將結果新增至輸入。如果擷取器處理錯誤,狀態的執行結果就是錯誤輸出。
因此,對於範例中的第一個擷取器,error-info
如果輸入中還沒有具有此名稱的欄位,則擷取器會將錯誤輸出新增為名為 的欄位。然後,擷取器會將整個輸入傳送至 RecoveryState
。對於第二個擷取器,錯誤輸出會覆寫輸入,而擷取器只會將錯誤輸出傳送至 EndState
。
注意
如未指定 ResultPath
欄位,它會預設為 $
,該值會選取並覆寫整個輸入。
當狀態同時具有 Retry
和 Catch
欄位時,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:region
: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:region
: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:region
: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:region
: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:region
: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:region
: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。