本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
处理 Step Functions 工作流程中的错误
除 Pass
和 Wait
状态之外的所有状态都可能遇到运行时错误。有多种原因可能导致错误发生,如以下所示:
-
状态机定义问题(例如,
Choice
状态中没有匹配规则) -
任务失败(例如, AWS Lambda 函数中的异常)
-
临时性问题(例如,网络分区事件)
默认情况下,当状态报告错误时, AWS Step Functions 会导致执行完全失败。
提示
要将包含错误处理的工作流程示例部署到您的中 AWS 账户,请参阅 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 中为分布式 Map 状态设置故障阈值。-
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
-
执行因某些无法处理的异常而失败。通常,这些错误是由运行时的错误引起的,例如尝试应用
InputPath
或OutputPath
在空JSON载荷上。States.Runtime
错误不可检索,并且始终会导致执行失败。在States.ALL
上重试或捕获不会捕获States.Runtime
错误。 -
States.TaskFailed
-
一个在执行期间失败的
Task
状态。在 retry 或 catch 中使用时,States.TaskFailed
充当通配符,可匹配除States.Timeout
之外的任何已知错误名称。 -
States.Timeout
-
一个
Task
状态,该状态要么运行时间长度超过TimeoutSeconds
值,要么在超过HeartbeatSeconds
值的时段长度中未能发送检测信号。此外,如果状态机的运行时间超过指定
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
的字段,其值必须是称为重试器 的对象数组。单个重试器表示特定的重试次数,通常是以递增的时间间隔。
当其中一个状态报告错误并且有一个 Retry
字段时,Step Functions 会按照数组中列出的顺序扫描重试器。当错误名称出现在某个重试器的 ErrorEquals
字段中时,状态机就会按照 Retry
字段中的定义进行重试。
如果您的 redriven 执行会重新运行Task 工作流程状态Parallel 工作流程状态、或 Inline Map 状态(您已为其定义了重试次数),这些状态的重试尝试次数将重置为 0 以允许最大尝试次数 redrive。 对于 redriven 执行,您可以使用控制台跟踪这些状态的单个重试尝试。有关更多信息,请参阅使用重启状态机执行 redrive 在 Step Functions中的的重试行为 redriven 处决。
重试器包含以下字段:
注意
重试被视为一种状态转换。有关状态转换如何影响计费的信息,请参阅 Step Functions 定价
-
ErrorEquals
(必需) -
一个匹配错误名称的非空字符串数组。当状态报告错误时,Step Functions 会全面扫描重试器。当错误名称出现在此数组中时,它实施该重试器描述的重试策略。
-
IntervalSeconds
(可选) -
一个正整数,表示第一次重试尝试之前等待的秒数(默认值为
1
)。IntervalSeconds
的最大值为 99999999。 -
MaxAttempts
(可选) -
一个正整数,表示重试的最大次数 (默认值为
3
)。如果错误重复发生超过指定次数,则停止重试并恢复正常错误处理。值为0
表示永不重试错误。MaxAttempts
的最大值为 99999999。 -
BackoffRate
(可选) -
每次重试后,
IntervalSeconds
所表示的重试间隔增加的倍数。默认情况下,BackoffRate
值会增加2.0
。例如,假设
IntervalSeconds
为 3,MaxAttempts
为 3,BackoffRate
为 2。第一次重试尝试在错误发生三秒后进行。第二次重试尝试在第一次重试尝试六秒后进行。而第三次重试尝试在第二次重试尝试 12 秒后进行。 -
MaxDelaySeconds
(可选) -
一个正整数,用于设置重试间隔可增加的最大值(以秒为单位)。该字段与
BackoffRate
字段配合使用会很有帮助。在此字段中指定的值将限制应用于每次连续重试尝试的回退率倍数所产生的指数等待时间。您必须为MaxDelaySeconds
指定一个大于 0 小于 31622401 的值。如果您未指定此值,则 Step Functions 不会限制两次重试尝试之间的等待时间。
-
JitterStrategy
(可选) -
一个字符串,用于确定是否在连续重试尝试之间的等待时间中包含抖动。抖动会将同时重试尝试的次数分散到一个随机的延迟时间间隔内,从而减少重试次数。此字符串可接受
FULL
或NONE
作为其值。默认值为NONE
。例如,您将
MaxAttempts
设置为 3,IntervalSeconds
设置为 2,BackoffRate
设置为 2。第一次重试尝试在错误发生两秒后进行。第二次重试在第一次重试尝试后四秒进行,第三次重试在第二次重试尝试后八秒进行。如果将JitterStrategy
设置为FULL
,则第一次重试间隔在 0 至 2 秒之间随机进行,第二次重试间隔在 0 至 4 秒之间随机进行,第三次重试间隔在 0 至 8 秒之间随机进行。
重试字段示例
本节包含以下 Retry
字段示例。
提示
要将错误处理工作流程的示例部署到您的 AWS 账户,请参阅 The Worksho AWS Step Functions p 的错误处理
示例 1-使用重试 BackoffRate
下面的 Retry
示例进行了两次重试,第一次重试在等待 3 秒后进行。根据指定的 BackoffRate
,Step Functions 会增加每次重试的间隔时间,直到达到重试尝试的最大次数。在下面的示例中,第二次重试在第一次重试 3 秒后开始。
"Retry": [ {
"ErrorEquals": [ "States.Timeout" ],
"IntervalSeconds": 3,
"MaxAttempts": 2,
"BackoffRate": 1
} ]
示例 2-使用重试 MaxDelaySeconds
以下示例进行了三次重试尝试,并将 BackoffRate
产生的等待时间限制为 5 秒。第一次重试在等待 3 秒钟后进行。由于 MaxDelaySeconds
设置了最长等待时间限制,第二次和第三次重试将在前一次重试后等待 5 秒后进行。
"Retry": [ {
"ErrorEquals": [ "States.Timeout" ],
"IntervalSeconds": 3,
"MaxAttempts": 3,
"BackoffRate":2,
"MaxDelaySeconds": 5,
"JitterStrategy": "FULL"
} ]
如果未设置 MaxDelaySeconds
,第二次重试将在第一次重试后 6 秒进行,第三次重试将在第二次重试后 12 秒进行。
示例 3 – 重试除 States.Timeout 之外的所有错误
重试器的 ErrorEquals
字段中显示的保留名称 States.ALL
是一个通配符,与所有错误名称匹配。它必须单独显示在 ErrorEquals
数组中,并且必须显示在 Retry
数组的最后一个重试器中。名称 States.TaskFailed
也是一个通配符,可匹配除 States.Timeout
以外的任何错误。
下面的 Retry
字段示例重试了除 States.Timeout
以外的任何错误。
"Retry": [ {
"ErrorEquals": [ "States.Timeout" ],
"MaxAttempts": 0
}, {
"ErrorEquals": [ "States.ALL" ]
} ]
示例 4 – 复杂的重试场景
在单状态执行的上下文中,重试器的参数应用到对该重试器的所有访问。
考虑以下 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"
} ]
}
此任务连续失败四次,输出以下错误名称:ErrorA
、ErrorB
、ErrorC
和 ErrorB
。出现以下结果:
-
前两个错误与第一个重试器匹配,导致等待 1 秒和 2 秒。
-
第三个错误与第二个重试器匹配,导致等待 5 秒。
-
第四个错误也与第一个重试器匹配。但是,针对该特定错误的两次重试 (
MaxAttempts
) 已达到最大值。因此,该重试器失败,执行会通过Catch
字段将工作流重定向到Z
状态。
回退状态
Task
、Map
和 Parallel
状态可以具有名为 Catch
的字段。此字段的值必须是称为捕获器 的对象的数组。
捕获器包含以下字段。
-
ErrorEquals
(必需) -
一个与错误名称匹配的非空字符串数组,由相同名称的重试器字段完全按其原样指定。
-
Next
(必需) -
一个字符串,必须与状态机的状态名称之一完全匹配。
-
ResultPath
(可选) -
一个路径,确定捕获器将什么输入发送到在
Next
字段中指定的状态。
当某个状态报告错误并且没有 Retry
字段或者重试无法解决错误时,Step Functions 按照数组中列出的顺序全面地扫描捕获器。当错误名称显示在捕获器的 ErrorEquals
字段中时,状态机转换为在 Next
字段中指定的状态。
捕获器的 ErrorEquals
字段中显示的保留名称 States.ALL
是一个通配符,与所有错误名称匹配。它必须单独显示在 ErrorEquals
数组中,并且必须显示在 Catch
数组的最后一个捕获器中。名称 States.TaskFailed
也是一个通配符,可匹配除 States.Timeout
以外的任何错误。
以下示例说明的是一个 Catch
字段,该字段在 Lambda 函数输出未处理的 Java 异常时转换为名为 RecoveryState
的状态。否则,该字段转换为 EndState
状态。
"Catch": [ {
"ErrorEquals": [ "java.lang.Exception" ],
"ResultPath": "$.error-info",
"Next": "RecoveryState"
}, {
"ErrorEquals": [ "States.ALL" ],
"Next": "EndState"
} ]
注意
每个捕获器可以指定多个要处理的错误。
错误输出
Step Functions 转换为 Catch 名称中指定的状态时,对象通常包含字段 Cause
。此字段的值是人类可读格式的错误说明。该对象称为错误输出。
在本示例中,第一个捕获器包含一个 ResultPath
字段。其工作方式类似于状态顶级中的 ResultPath
字段,有两种可能的结果:
-
它获取状态执行的结果,并覆盖状态的全部或部分输入。
-
它获取结果并将其添加到输入中。在由捕获器处理错误时,状态执行的结果是错误输出。
因此,在本示例中,对于第一个捕获器,如果输入中还没有名为 error-info
的字段,捕获器就会将错误输出添加到输入中。然后,捕获器会将整个输入发送到 RecoveryState
。对于第二个捕获器,错误输出会覆盖输入,捕获器只会将错误输出发送到 EndState
。
注意
如果您不指定 ResultPath
字段,则它会默认为 $
,这会选择和覆盖整个输入。
当状态同时包含 Retry
和 Catch
字段时,Step Functions 会首先使用任何合适的重试器。如果重试策略无法解决错误,Step Functions 会应用匹配的捕获器转换。
原因有效负载和服务集成
捕获器会返回一个字符串有效负载作为输出。在使用诸如 Amazon AWS CodeBuild Athena 或之类的服务集成时,您可能需要将Cause
字符串转换为。JSON以下带有内部函数的Pass
状态示例显示了如何将Cause
字符串转换为。JSON
"Handle escaped JSON with JSONtoString": {
"Type": "Pass",
"Parameters": {
"Cause.$": "States.StringToJson($.Cause)"
},
"Next": "Pass State with Pass Processing"
},
使用 Retry 和使用 Catch 的状态机示例
以下示例中定义的状态机假定存在两个 Lambda 函数:一个始终失败,另一个等待足够长的时间,以允许发生状态机中定义的超时。
这是始终失败的 Lambda 函数的定义,返回消息 error
。在后面的状态机示例中,此 Lambda 函数名为 FailFunction
。有关创建 Lambda 函数的信息,请参阅第 1 步:创建 Lambda 函数部分。
exports.handler = (event, context, callback) => {
callback("error");
};
这是一个休眠 10 秒的 Lambda 函数的定义。在后面的状态机示例中,此 Lambda 函数名为 sleep10
。
注意
当您在 Lambda 控制台中创建此 Lambda 函数时,请记住在 Advanced settings 部分中将 Timeout 值从 3 秒 (默认值) 更改为 11 秒。
exports.handler = (event, context, callback) => {
setTimeout(function(){
}, 11000);
};
使用 Retry 处理失败
此状态机使用 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 处理超时
此状态机根据在 TimeoutSeconds
中指定的超时值,使用 Retry
字段重试超时的 Task
状态。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 用于在 a 中同时包含错误和输入 Catch。