本文档介绍了如何为事件驱动型 Cloud Run functions 函数启用重试。HTTP 函数无法自动重试。
为什么事件驱动型函数会执行失败
在极少数情况下,函数可能会由于内部错误而提早退出,并且默认情况下函数可能会自动重试,也可能不会自动重试。
更常见的情况是,事件驱动型函数可能由于函数代码本身抛出错误而无法成功完成。可能导致这种情况的原因包括:
- 函数包含 bug,且运行时抛出异常。
- 函数无法访问服务端点,或者在尝试访问端点时超时。
- 函数本身有意抛出异常(例如,某个参数验证失败)。
- Node.js 函数返回遭拒的 promise,或将非
null值传递给回调。
在上述任何情况下,函数都会停止执行并返回错误。生成消息的事件触发器具有重试政策,您可以自定义这些政策以满足您函数的需求。
重试的语义
对于事件来源发出的每个事件,Cloud Run functions 保证至少执行一次事件驱动型函数。 您配置重试的方式取决于您创建函数的方式:
在 Google Cloud 控制台中或使用 Cloud Run Admin API 创建函数时,您需要单独创建和管理事件触发器。触发器具有默认重试行为,您可以根据函数需求进行自定义。
一般来说,您无法停用函数的重试功能(使用 Cloud Functions v2 API 创建的函数除外,此类函数的重试功能默认处于停用状态)。您无法为基于 Cloud Run Admin API 的函数停用重试功能。
使用 Cloud Functions v2 API 创建函数时,Cloud Functions v2 API 会隐式创建必要的事件触发器,例如 Pub/Sub 主题或 Eventarc 触发器。默认情况下,这些触发器的重试功能处于停用状态,但您可以使用 Cloud Functions v2 API 启用该功能。
无论您的函数(含 Pub/Sub 触发器)基于哪个 API,都无法使用“仅一次”消息传送功能。该设置仅适用于拉取订阅,不适用于推送订阅。函数使用推送订阅。
使用 Cloud Run 创建的事件驱动型函数
在 Google Cloud 控制台中或使用 Cloud Run Admin API 创建的函数,需要您单独创建和管理事件触发器。我们强烈建议您查看每种触发器类型的默认行为:
- Eventarc 重试政策的默认消息保留时长为 24 小时,具有指数退避算法延迟。请参阅有关重试事件的 Eventarc 文档。
- Pub/Sub 默认对所有订阅使用立即重新传送政策。请参阅有关处理消息故障和重试请求的 Pub/Sub 文档。
使用 Cloud Functions v2 API 创建的事件驱动型函数
使用 Cloud Functions v2 API 创建的函数(例如,使用 Cloud Functions gcloud CLI、REST API 或 Terraform)将代表您创建和管理事件触发器。 默认情况下,如果函数调用因错误而终止,则该函数不会被再次调用,且相应事件会被丢弃。当您针对事件驱动型函数启用重试时,Cloud Run functions 会重试失败的函数调用,直到该函数调用成功或重试期限到期。
如果没有为函数启用重试(默认设置),则函数始终报告其成功执行,并且 200 OK 响应代码可能出现在其日志中。即使函数出现错误,也会发生这种情况。为了清楚说明函数何时出现错误,请务必适当地报告错误。
启用或停用重试
如需启用或停用重试,您可以使用 Google Cloud CLI。默认情况下,不允许重试。
通过 Google Cloud CLI 配置重试
如需使用 Google Cloud CLI 启用重试,请在部署函数时添加 --retry 标志:
gcloud functions deploy FUNCTION_NAME --retry FLAGS...
要停用重试功能,请重新部署不使用 --retry 标志的函数:
gcloud functions deploy FUNCTION_NAME FLAGS...
重试期限
此重试期限会在 24 小时后到期。Cloud Run functions 会使用指数退避算法策略重试新创建的事件驱动型函数,退避时间范围为 10 到 600 秒,逐步增加。最佳做法
本部分介绍有关如何利用重试的最佳做法。
利用重试来应对暂时性错误
由于函数会一直重试,直到成功执行为止,因此在启用重试之前应进行彻底的测试,以从代码中清除错误之类的永久性错误。重试最适合用于应对较有可能通过重试解决的间歇性或暂时性故障,比如不稳定的服务端点或超时。
设置结束条件以避免无限重试循环
在启用重试时,您应防止函数陷入连续循环。您可以在函数开始处理之前添加明确定义的结束条件。请注意,此方法仅在您的函数成功启动并且能够评估结束条件时才有效。
一种简单而有效的方法是舍弃时间戳早于特定时间的事件。在发生永久性故障或持续时间长于预期的故障时,这样可以保证函数执行次数不会太多。
例如,以下代码段会舍弃超过 10 秒前发生的所有事件: