事件被拒的原因有很多。例如,事件接收器服务可能会因服务中断而暂时不可用;服务在处理事件时可能会遇到错误;或者服务资源可能会耗尽。遇到此类暂时性错误时,可以重试。
事件也可能会无法传送到事件接收器。例如,事件可能与配置的预期架构不符,或者事件消息在路由到最终目的地之前,事件中介可能会失败。此类情况会导致持续性错误。
暂时性错误
Eventarc Advanced 可让您处理暂时性错误。这些暂时性错误可以重试,包括以下错误代码:
- HTTP
408 Request Timeout
- HTTP
409 Conflict
- HTTP
429 Too Many Requests
- HTTP
500 Internal Server Error
- HTTP
502 Bad Gateway
- HTTP
503 Service Unavailable
- HTTP
504 Gateway Time-out
持续性错误
与暂时性错误相比,持续性错误包括:
- 配置的重试次数用尽时发生的错误
- 事件在无法路由到目的地之前失败时发生的错误
- 导致错误代码被视为不可重试的错误;例如,暂时性错误所列错误代码以外的错误代码
您可以手动识别持续性错误并妥善处理。
重试暂时性错误
Eventarc Advanced 使用通过指数退避算法确定的延迟时间来处理可重试的错误。默认重试政策从 1 秒延迟开始,每次尝试失败后延迟时间都会翻倍(最多 60 秒,最多 5 次尝试)。
您可以使用 Google Cloud 控制台或 gcloud beta eventarc pipelines update
命令更改默认重试政策。
请注意,2
的默认回退因子无法更改。
控制台
在 Google Cloud 控制台中,前往 Eventarc > 流水线页面。
点击流水线的名称。
在流水线详情页面中,点击修改。
在修改流水线页面的重试政策部分,修改以下字段:
- 重试次数上限:重试次数;默认为
5
次。可以是任何正实数。如果设置为1
,则不会应用任何重试政策,即仅会尝试传送一次消息。 - 延迟时间下限(秒):初始延迟时间(以秒为单位);默认值为
1
秒。必须介于1
到600
之间。 - 延迟时间上限(秒):延迟时间上限(以秒为单位);默认值为
60
秒。必须介于1
到600
之间。
您可以将最小延迟时间和最大延迟时间设置为相同的值,以配置线性回退。
- 重试次数上限:重试次数;默认为
点击保存。
gcloud
gcloud beta eventarc pipelines update PIPELINE_NAME \
--min-retry-delay=MIN_DELAY \
--max-retry-delay=MAX_DELAY \
--max-retry-attempts=MAX_ATTEMPTS
替换以下内容:
PIPELINE_NAME
:流水线的 ID 或完全限定标识符。MIN_DELAY
:初始延迟时间(以秒为单位);默认值为1
秒。必须介于1
到600
之间。MAX_DELAY
:延迟时间上限(以秒为单位);默认值为60
秒。必须介于1
到600
之间。MAX_ATTEMPTS
:重试次数;默认值为5
次。可以是任何正实数。如果设置为1
,则不会应用任何重试政策,即仅会尝试传送一次消息。
以下示例通过将最短延迟时间和最长延迟时间设置为相同的值来配置线性退避:
gcloud beta eventarc pipelines update my-pipeline \
--min-retry-delay=4 \
--max-retry-delay=4 \
--max-retry-attempts=5
归档消息以处理持续性错误
您可以将消息在收到时写入 BigQuery 表。这样,您就可以手动识别持续性错误并妥善处理它们。
以下部分概要介绍了归档事件消息、识别持续性错误和重试受影响事件所需执行的步骤。
- 创建总线。适当地配置该总线;例如,发布来自 Google 来源的事件。
- 创建 Pub/Sub 主题。此 Pub/Sub 主题将成为流水线的目标目的地。
- 为 Pub/Sub 主题创建 BigQuery 订阅。BigQuery 订阅是一种导出订阅,可在收到消息时将其写入现有 BigQuery 表。或者,您也可以在创建 BigQuery 订阅时创建表。
创建流水线和注册,将总线收到的每条消息(使用
--cel-match="true"
)路由到 Pub/Sub 主题。为流水线配置重试政策。例如,以下命令会创建流水线和注册:
gcloud beta eventarc pipelines create my-archive-pipeline \ --destinations=pubsub_topic='my-archive-topic',network_attachment='my-network-attachment' \ --min-retry-delay=1 \ --max-retry-delay=20 \ --max-retry-attempts=6 \ --location=us-central1
gcloud beta eventarc enrollments create my-archive-enrollment \ --cel-match="true" \ --destination-pipeline=my-archive-pipeline \ --message-bus=my-message-bus \ --message-bus-project=my-google-cloud-project \ --location=us-central1
将流水线日志路由到另一个 BigQuery 数据集。
现在,您应该有两个单独的 BigQuery 数据集:一个用于存储 Eventarc Advanced 总线收到的每条消息,另一个用于存储流水线日志。
如需识别失败的消息,请使用查询语句联接这两个 BigQuery 数据集(基于
message_uid
字段)。找到任何失败的消息后,您可以使用 Eventarc Publishing API 将其重新发布到总线。例如,您可以部署 Cloud Run 服务或作业来读取 BigQuery 中的消息,并直接将其发布到 Eventarc Advanced 总线。
使事件处理脚本具有幂等性
可重试的事件处理脚本应遵循以下一般准则,以确保幂等性:
- 许多外部 API 允许您提供幂等键作为参数。如果您在使用此类 API,应将事件来源和 ID 作为幂等键。(生产者必须确保每个不同的事件的 source + id 是唯一的。)
- 此外,您还可以使用 CloudEvents 属性
xgooglemessageuid
来实现幂等性。此属性的值与 Eventarc Advanced 消息中的message_uid
字段相同。它用于唯一标识发布事件的操作。例如,如果将同一事件发布到总线两次,则每个事件在发送到事件处理脚本时都会具有不同的xgooglemessageuid
值。 - 幂等性与“至少一次”机制非常契合,因为它能确保重试的安全性。通常情况下,幂等性对于重试来说是不可或缺的。
- 确保代码具有内在的幂等性。例如:
- 确保即使发生多次变更 (mutation),执行结果也不会改变。
- 在事务中,先查询数据库状态再更改状态。
- 确保所有副作用本身也具有幂等性。
- 在服务之外强制执行事务检查(不依赖代码)。 例如,在某个位置留存状态信息,并记录已处理事件的 ID。
- 处理重复的带外调用。例如,设置一个单独的清理进程,在发生重复调用后执行清理。