订阅者可能无法处理消息,原因有很多。例如,在检索处理消息所需的数据时,可能会出现暂时性问题。或者,消息的格式可能与订阅者预期不符。
本页介绍了如何通过使用订阅重试政策或将未送达的消息转发到死信主题(也称为“死信队列”)来处理此类处理失败。
请注意,Dataflow 不支持这些功能。如需了解详情,请参阅 Dataflow 文档的不支持的 Pub/Sub 功能部分。
订阅重试政策
如果 Pub/Sub 尝试传送消息,但订阅者无法确认消息,Pub/Sub 会自动尝试重新发送消息。这种重新提交尝试称为“订阅重试政策”。这不是您可以开启或关闭的功能。不过,您可以选择要使用的重试政策类型。
首次创建和配置订阅时,您可以选择使用以下重试政策之一:立即重新提交或指数退避算法。默认情况下,订阅使用立即重新提交。
立即重新提交
默认情况下,Pub/Sub 会立即尝试重新发送消息(可能会发送到同一订阅方客户端)。但是,如果阻止消息确认的条件没有改变,立即重新传送可能会导致问题。在这种情况下,Pub/Sub 可能会重新发送多个无法确认的消息。
为了解决立即重新提交问题,Pub/Sub 允许您配置指数退避算法政策。
指数退避算法
借助指数退避,您可以在重试尝试之间逐步增加延迟时间。第一次传送失败后,Pub/Sub 会等待最短退避时间,然后再重试。对于消息的每次连续失败,系统会延长延迟时间,直至达到最长延迟时间(0 到 600 秒)。
最大和最小延迟间隔不固定,应根据应用的本地因素进行配置。
请注意以下有关指数退避算法的注意事项:
- 指数退避算法会在以下操作执行时触发:
- 收到否定确认时。
- 消息的确认截止期限到期。
- 指数退避仅应用于每条消息,而不是应用于订阅中的所有消息(全局)。
- 使用指数退避算法时,即使之前的消息收到了否定确认,Pub/Sub 也会继续传送其他消息(除非您使用有序消息传送)。
使用重试政策来延迟部分消息的传送和处理,以应对在传送时无法处理某些消息的暂时性问题。系统会尽力应用此功能,并对每封邮件单独评估重试政策。
我们不建议您使用此功能故意延迟消息传送。如果您对使用重试政策配置的订阅中的大量消息做出否定确认 (nack),则其中一些消息在传送时可能会减少退避次数或不退避。如果您大量回绝消息,Pub/Sub 也可能会减慢所有消息的传送速度。
如果您需要安排传送时间,请考虑使用 Cloud Tasks。
配置指数退避算法
控制台
创建新订阅时,您可以执行以下步骤来配置指数退避算法重试政策:
gcloud
如需使用指数退避算法重试政策创建新订阅,请使用下面显示的标志运行 gcloud pubsub create
命令:
gcloud pubsub subscriptions create SUBSCRIPTION_ID \ --topic=TOPIC_ID \ --min-retry-delay=MIN_RETRY_DELAY \ --max-retry-delay=MAX_RETRY_DELAY
死信主题
如果 Pub/Sub 服务尝试传送消息,但订阅者无法确认消息,则 Pub/Sub 可以将无法传送的消息转发到死信主题。
死信主题如何与 Pub/Sub 搭配使用
死信主题是订阅属性,而不是主题属性。这意味着,您是在创建订阅时设置死信主题,而不是在创建主题时设置。
如果您创建了死信主题,则可以设置以下订阅属性:
传送尝试次数上限:一个数值,表示 Pub/Sub 针对特定消息进行的传送尝试次数。如果订阅方客户端在配置的传送尝试次数内无法确认消息,系统会将消息转发到死信主题。
- 默认值 = 5
- 最大值 = 100
- 最小值 = 5
含有死信主题的项目:如果死信主题与订阅位于不同项目中,则您必须指定含有死信主题的项目。将死信主题设置为与订阅附加到的主题不同的主题。
如何计算传送尝试次数上限
只有在死信主题配置正确且包含正确的 IAM 权限时,Pub/Sub 才会统计传送尝试次数。
传送尝试次数上限是近似值,因为 Pub/Sub 会尽力转发无法传送的消息。
系统跟踪的消息传送尝试次数也可能会重置为零,尤其是对于包含不活跃订阅者的拉取订阅。因此,消息传送给订阅者客户端的次数可能会超过配置的传送尝试次数上限。
配置死信主题
如需配置死信主题,来源主题必须先有订阅。您可以在创建订阅时指定死信主题,也可以更新现有订阅以添加死信主题。
以下是针对订阅启用死信的工作流程。
创建死信主题。此主题与来源主题是分开的。
在来源主题的订阅中设置死信主题。
为避免丢失死信主题中的消息,请将至少一个其他订阅附加到死信主题。辅助订阅会接收来自死信主题的消息。
向 Pub/Sub 服务账号授予发布商和订阅者角色。如需了解详情,请参阅授予转发权限。
为新订阅设置死信主题
您可以使用 Google Cloud 控制台、Google Cloud CLI、客户端库或 Pub/Sub API 创建订阅并设置死信主题。
控制台
如需创建订阅并设置死信主题,请完成以下步骤:
在 Google Cloud 控制台中,进入订阅页面。
点击创建订阅。
输入订阅 ID。
从下拉菜单中选择或创建一个主题。
订阅将接收来自该主题的消息。
在死信部分,选择启用死信。
从下拉菜单中选择或创建死信主题。
如果所选的死信主题没有订阅,系统会提示您创建一个订阅。
在最大传送尝试字段中,指定一个 5 到 100 之间的整数。
点击创建。
详情面板会显示可能的操作列表。如果任何项目显示错误图标
,请点击相应操作项以解决问题。
gcloud
如需创建订阅并设置死信主题,请使用 gcloud pubsub subscriptions create
命令:
gcloud pubsub subscriptions create subscription-id \ --topic=topic-id \ --dead-letter-topic=dead-letter-topic-name \ [--max-delivery-attempts=max-delivery-attempts] \ [--dead-letter-topic-project=dead-letter-topic-project]
C++
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 C++ 设置说明进行操作。如需了解详情,请参阅 Pub/Sub C++ API 参考文档。
C#
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 C# 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub C# API 参考文档。
Go
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 Go 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Go API 参考文档。
Java
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 Java 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Java API 参考文档。
Node.js
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 Node.js 设置说明进行操作。如需了解详情,请参阅 Pub/Sub Node.js API 参考文档。
Node.js
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 Node.js 设置说明进行操作。如需了解详情,请参阅 Pub/Sub Node.js API 参考文档。
PHP
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 PHP 设置说明进行操作。如需了解详情,请参阅 Pub/Sub PHP API 参考文档。
Python
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 Python 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Python API 参考文档。
Ruby
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 Ruby 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Ruby API 参考文档。
Ruby
在尝试此示例之前,请按照 Pub/Sub 快速入门:使用客户端库中的 Ruby 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Ruby API 参考文档。
如需向 Pub/Sub 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证。
为现有订阅设置死信主题
您可以使用 Google Cloud 控制台、Google Cloud CLI、客户端库或 Pub/Sub API 更新订阅并设置死信主题。
控制台
如需更新订阅并设置死信主题,请完成以下步骤。
在 Google Cloud 控制台中,进入订阅页面。
在要更新的订阅旁边,点击更多操作more_vert。
在上下文菜单中,选择编辑。
在死信部分,选择启用死信。
从下拉菜单中选择或创建一个主题。
如果所选主题没有订阅,系统会提示您创建一个订阅。
在最大传送尝试字段中,指定一个 5 到 100 之间的整数。
点击更新。
详情面板会显示可能的操作列表。如果任何项目显示错误图标
,请点击相应操作项以解决问题。
gcloud
如需更新订阅并设置死信主题,请使用 gcloud pubsub subscriptions update
命令:
gcloud pubsub subscriptions update subscription-id \ --dead-letter-topic=dead-letter-topic-name \ [--max-delivery-attempts=max-delivery-attempts] \ [--dead-letter-topic-project=dead-letter-topic-project]
C++
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 C++ 设置说明进行操作。如需了解详情,请参阅 Pub/Sub C++ API 参考文档。
C#
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 C# 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub C# API 参考文档。
Go
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 Go 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Go API 参考文档。
Java
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 Java 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Java API 参考文档。
Node.js
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 Node.js 设置说明进行操作。如需了解详情,请参阅 Pub/Sub Node.js API 参考文档。
PHP
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 PHP 设置说明进行操作。如需了解详情,请参阅 Pub/Sub PHP API 参考文档。
Python
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 Python 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Python API 参考文档。
Ruby
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 Ruby 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Ruby API 参考文档。
Ruby
在尝试此示例之前,请按照 Pub/Sub 快速入门:使用客户端库中的 Ruby 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Ruby API 参考文档。
如需向 Pub/Sub 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证。
向 IAM 角色授予使用死信主题的权限
如需将无法传送的消息转发到死信主题,Pub/Sub 必须具有执行以下操作的权限:
- 将消息发布到主题。
- 确认消息,这会将这些消息从订阅中移除。
Pub/Sub 会为每个项目创建并维护一个服务账号:service-project-number@gcp-sa-pubsub.iam.gserviceaccount.com
。您可以通过将发布者和订阅者角色分配给此服务账号来授予转发权限。
控制台
如需向 Pub/Sub 授予将消息发布到死信主题的权限,请完成以下步骤:
在 Google Cloud 控制台中,进入订阅页面。
点击包含死信主题的订阅的名称。
点击死文字标签页。
如需分配发布商角色,请点击授予发布商角色。如果成功分配发布商角色,您会看到蓝色对勾图标
。如需分配订阅者角色,请点击授予订阅者角色。如果成功分配发布商角色,您会看到蓝色对勾图标
。
gcloud
如需授予 Pub/Sub 将消息发布到死信主题的权限,请运行以下命令:
PUBSUB_SERVICE_ACCOUNT="service-project-number@gcp-sa-pubsub.iam.gserviceaccount.com" gcloud pubsub topics add-iam-policy-binding dead-letter-topic-name \ --member="serviceAccount:$PUBSUB_SERVICE_ACCOUNT"\ --role="roles/pubsub.publisher"
如需授予 Pub/Sub 确认转发的无法传送的消息的权限,请运行以下命令:
PUBSUB_SERVICE_ACCOUNT="service-project-number@gcp-sa-pubsub.iam.gserviceaccount.com" gcloud pubsub subscriptions add-iam-policy-binding subscription-id \ --member="serviceAccount:$PUBSUB_SERVICE_ACCOUNT"\ --role="roles/pubsub.subscriber"
跟踪传送尝试
为订阅启用死信主题后,该订阅中的每条消息都会包含一个字段,用于指定传送尝试次数:
从拉取订阅收到的消息将包含
delivery_attempt
字段。从推送订阅收到的消息将包含
deliveryAttempt
字段。
以下示例展示了如何获取传送尝试次数:
C++
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 C++ 设置说明进行操作。如需了解详情,请参阅 Pub/Sub C++ API 参考文档。
C#
在尝试此示例之前,请按照 Pub/Sub 快速入门:使用客户端库中的 C# 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub C# API 参考文档。
如需向 Pub/Sub 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证。
Go
在尝试此示例之前,请按照 Pub/Sub 快速入门:使用客户端库中的 Go 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Go API 参考文档。
如需向 Pub/Sub 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证。
Java
在尝试此示例之前,请按照 Pub/Sub 快速入门:使用客户端库中的 Java 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Java API 参考文档。
如需向 Pub/Sub 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证。
Node.js
在尝试此示例之前,请按照 Pub/Sub 快速入门:使用客户端库中的 Node.js 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Node.js API 参考文档。
如需向 Pub/Sub 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证。
PHP
在尝试此示例之前,请按照 Pub/Sub 快速入门:使用客户端库中的 PHP 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub PHP API 参考文档。
如需向 Pub/Sub 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证。
Python
在尝试此示例之前,请按照 Pub/Sub 快速入门:使用客户端库中的 Python 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Python API 参考文档。
如需向 Pub/Sub 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证。
Ruby
在尝试此示例之前,请按照 Pub/Sub 快速入门:使用客户端库中的 Ruby 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Ruby API 参考文档。
如需向 Pub/Sub 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证。
当 Pub/Sub 将无法传送的消息转发到死信主题时,会向消息添加以下属性:
CloudPubSubDeadLetterSourceDeliveryCount
:向来源订阅提交内容的尝试次数。CloudPubSubDeadLetterSourceSubscription
:来源订阅的名称。CloudPubSubDeadLetterSourceSubscriptionProject
:包含来源订阅的项目的名称。CloudPubSubDeadLetterSourceTopicPublishTime
:消息最初发布的时间戳。CloudPubSubDeadLetterSourceDeliveryErrorMessage
:邮件无法递送到原始目的地的具体原因。此属性仅适用于导出订阅。
监控转发的消息
转发无法送达的消息后,Pub/Sub 服务会从订阅中移除消息。您可以使用 Cloud Monitoring 监控转发的消息。
如果您将订阅附加到死信主题,则这些消息会使用附加订阅的到期政策,而非具有死信主题属性的订阅的有效期。
subscription/dead_letter_message_count
指标用于记录 Pub/Sub 从订阅转发的无法传送的消息数量。
如需了解详情,请参阅监控转发的无法传送的消息。
移除死信主题
如需停止转发无法传送的消息,请从订阅中移除死信主题。
您可以使用 Google Cloud 控制台、Google Cloud CLI 或 Pub/Sub API 从订阅中移除死信主题。
控制台
如需从订阅中移除死信主题,请完成以下步骤:
在 Google Cloud 控制台中,进入订阅页面。
在订阅列表中,点击订阅旁边的 more_vert 进行更新。
从上下文菜单中选择修改。
在死信部分,清除启用死信。
点击更新。
gcloud
如需从订阅中移除死信主题,请使用 gcloud pubsub subscriptions update
命令和 --clear-dead-letter-policy
标志:
gcloud pubsub subscriptions update subscription-id \ --clear-dead-letter-policy
C++
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 C++ 设置说明进行操作。如需了解详情,请参阅 Pub/Sub C++ API 参考文档。
C#
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 C# 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub C# API 参考文档。
Go
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 Go 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Go API 参考文档。
Java
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 Java 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Java API 参考文档。
Node.js
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 Node.js 设置说明进行操作。如需了解详情,请参阅 Pub/Sub Node.js API 参考文档。
PHP
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 PHP 设置说明进行操作。如需了解详情,请参阅 Pub/Sub PHP API 参考文档。
Python
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 Python 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Python API 参考文档。
Ruby
在尝试此示例之前,请按照《快速入门:使用客户端库》中的 Ruby 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Ruby API 参考文档。
Ruby
在尝试此示例之前,请按照 Pub/Sub 快速入门:使用客户端库中的 Ruby 设置说明进行操作。 如需了解详情,请参阅 Pub/Sub Ruby API 参考文档。
如需向 Pub/Sub 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为本地开发环境设置身份验证。
价格
Pub/Sub 服务转发无法传送的消息时,您需要支付以下费用:
- 向与包含死信主题的项目相关联的结算账号计入的发布费用。
- 向与包含具有死信主题的订阅的项目相关联的结算账号收取的出站消息订阅费用。
如果您设置了订阅的死信主题属性,但死信主题的消息存储位置政策不允许包含该订阅的区域,则还需要支付出站消息的发布费用。
出站消息的发布费用将计入包含死信主题的项目。要了解详情,请参阅价格。