本文档假定您已熟悉订阅 Pub/Sub 主题并在订阅者客户端中接收消息的过程。
如果您刚开始接触 Pub/Sub,请参阅其中一个快速入门指南,了解如何使用控制台、Google Cloud CLI 或客户端库运行 Pub/Sub。
选择合适的订阅
Pub/Sub 提供标准订阅,例如推送和拉取订阅。除了标准订阅之外,Pub/Sub 还提供导出订阅,可让您将消息直接存储到Google Cloud 资源,而无需使用 Dataflow 作为中介。例如,BigQuery 订阅会将消息存储在 BigQuery 表中。
建议在以下场景中使用推送订阅:
您不能在订阅者应用中包含任何将客户端库作为依赖项导入的代码。
订阅者客户端无法发出任何传出请求。
您希望使用同一实例来处理来自不同主题和订阅的消息,其中订阅者客户端不知道订阅列表。
对于一般情况,我们建议使用高级客户端库。如果您使用的是一元拉取,请勿将 returnImmediately 设置为 true。将其设置为 true 会对拉取性能产生不利影响。returnImmediately 字段现已弃用。
如需比较所有订阅类型并选择最适合您业务需求的订阅类型,请参阅 Pub/Sub 订阅比较表。
如需了解导出订阅的好处,请参阅何时使用导出订阅。
在确认消息之前处理消息
默认情况下,Pub/Sub 会在消息确认后从订阅中舍弃该消息。如果您在发送确认之前未处理消息,并且处理失败,则服务不会重新传送消息。例外情况是,当您配置了保留已确认的消息或主题保留,并且执行跳转操作时。
如果您有高延迟订阅者,则可能需要为流控制和租约管理设置自定义值。
保留消息 ID
为了更轻松地进行问题排查,发布者和订阅者应保留已发布消息的消息 ID。您可以存储每条已发布消息的 ID,也可以根据需要启用消息 ID 日志记录。保留消息 ID 有助于更轻松地排查重复消息、重新传送、数据丢失和其他常见问题。如需了解详情,请参阅处理重复项。
针对瞬时流量高峰配置订阅者流控制
订阅者端的流控制可防止订阅者因流量高峰而过载。它可以让自动扩缩机制有时间响应增加的负载,也可以在更长的时间内分散负载的处理。前一种方法可以缩短延迟时间,而后一种方法可以节省费用。
如需配置流控制,您必须为 maximum outstanding messages 和 total outstanding message bytes 设置适当的值。这些流控制变量的默认值和变量名称可能因客户端库而异。
未完成消息数上限定义了 Pub/Sub 尚未收到确认或否定确认的已传递给客户端的消息数上限。
未完成消息总字节数定义了 Pub/Sub 尚未收到确认或否定确认的已传送给客户端的消息的最大总大小。
如果超出其中一个选项的限制,订阅者客户端将不会拉取更多消息。此行为会一直持续,直到已拉取的消息得到确认或否定确认为止。这样,您就可以在吞吐量与运行更多订阅者相关的费用之间进行权衡。
处理重复递送
默认情况下,Pub/Sub 会向订阅者提供至少一次的消息传送。这意味着,即使消息已确认,也可能会多次传送。以下部分介绍了如何处理常见的重新传送场景。
持续重新递送多条消息
如果您遇到许多消息总是被重新传送的情况,则说明您的订阅者过载,或者他们未在截止期限之前确认消息。
如果您使用的是拉取订阅,则可能需要将自定义值设置为流控制值,或使用租约管理增加租约延长期限。
如果您使用的是推送订阅,则可能需要增加确认截止期限设置。您还可以遵循有关如何维持健康的订阅的最佳实践。
偶尔重新递送消息
当您看到消息在确认截止期限之前或在消息确认后的几秒钟内重新传送时,Pub/Sub 的行为符合预期。您应该不会经常看到这些重新提交高峰,但当重新提交确实发生时,它们可能会同时发生在多条消息上。您的系统必须能够容忍这些偶尔出现的重复项。
重复重新递送少量邮件
如果您发现有少量消息被多次传递,请先确认您是否正在确认这些消息。如果不是,请找出订阅者无法正确处理消息的原因。您可能需要配置死信主题,以防止进一步重新传送。如果您正在确认消息,Pub/Sub 可能仍会按预期运行。虽然这种情况非常罕见,但如果发生内部网络或硬件中断,仍有可能多次传送少量消息。在这些情况下,服务会尝试自行修复,但修复措施可能需要几分钟才能生效。
您的系统必须能够容忍重新传送。您可以通过确保尽快处理和确认消息来降低其可能性。
如果您的应用无法容忍任何重复,您可以启用仅传送一次。请注意,此功能仅适用于拉取订阅,并且会导致发布到订阅的延迟时间更长。在启用此功能之前,请评估延迟时间增加的代价对于您的应用场景是否可以接受。
订阅中有序消息传递的最佳实践
如果您使用消息排序,请确保满足以下条件:
选择 StreamingPull 或 拉取订阅。对于推送订阅,Pub/Sub 一次仅支持每个排序键一条未完成的消息。在这种情况下,发送并行推送请求类似于同时向拉取订阅者发送具有相同排序键的多批消息。因此,对于经常使用相同排序键发布多条消息的主题,或者对延迟时间要求极高的主题,不建议使用推送订阅。
在订阅中启用消息排序。在发布方,如果您发送的消息具有排序键且位于同一区域,则可以将订阅方配置为按顺序接收这些消息。在订阅者端,仅为要接收有序消息的订阅启用消息排序属性。根据属性状态,附加到主题的每个订阅都可以确定是否需要有序传送,而不会相互影响。
按顺序确认消息。使用有序传送时,系统会先处理较早消息的确认,然后再处理较晚消息的确认(按排序键)。例如,如果您有消息 1、2 和 3,它们具有相同的排序键,并且您收到了所有这些消息,但仅确认了消息 3,则服务不会将消息 3 视为已确认,直到消息 1 和 2 也被确认。如果系统从未收到消息 1 和 2 的确认,则消息 1、2 和 3 都会重新传送。
最佳做法摘要
下表总结了本文档中建议的最佳做法。
| 主题 | 任务 |
|---|---|
| 选择订阅类型 | 根据您的业务需求选择合适的订阅类型。如果您的订阅支持,请同时使用高级客户端库。 |
| 重放已确认的消息 | 在确认消息之前先处理消息。或者,配置跳转操作,以免丢失已确认的消息。 |
| 流控制 | 在订阅者设置中配置流控制,以确保订阅者在自动扩缩生效或时间过去之前不会过载。 |
| 处理重复传送并保留消息 ID | 保留或启用所接收 messageId 的日志记录,以简化对重复、重新传送和缺失消息的问题排查。 |
| 消息排序 | 使用有序消息传递时,请选择 StreamingPull 或 Pull,在订阅中启用消息排序,并按顺序确认消息。 |