排查拉取订阅问题

本文档提供了有关 Pub/Sub 拉取订阅的一些常见问题排查提示。如需详细了解拉取订阅,请参阅拉取订阅者指南

为了有效监控 Pub/Sub 订阅,建议您先查看传送延迟时间运行状况得分 (subscription/delivery_latency_health_score),检查哪些因素会导致延迟时间意外增加或增加。

最早的未确认消息的存在时间不断增加

oldest_unacked_message_age 是监控 Pub/Sub 订阅运行状况的关键指标。它测量订阅积压中尚未被订阅者确认(确认)的最旧消息的存在时间(以秒为单位)。此指标可提供有价值的数据洞见,帮助您了解潜在的处理延迟或瓶颈。

监控消息积压可确保及时高效地处理消息。通过跟踪最早的未确认消息的存在时间,您可以主动发现消费者落后的情况。这种做法有助于及早进行干预,解决与表现下降相关的潜在问题。

您可以调查的一些常见的积压问题包括:

客户端配置问题

oldest_unacked_message_agenum_undelivered_messages 指标同时增加时,可能意味着订阅者未跟上消息量。在这种情况下,请将调查重点放在订阅者组件上:

  • 客户端健康状况:分析托管订阅者客户端的机器上的资源利用率,例如 CPU、内存和网络带宽。寻找可能会影响处理效率的压力点。

  • 客户端代码:查看最近的代码更改和错误日志。订阅者代码中的错误或低效问题可能会严重影响消息处理速率。请注意,特定消息中可能存在问题。例如,多条消息可能需要同时访问数据库中的同一行。此行为可能导致争用和高延迟。

  • 配额限制:确认您未超出托管服务施加的任何 Pub/Sub 配额或限制。如果订阅者托管在 Google Cloud 中,请查看 Compute EngineGKE 资源配额,以防止出现潜在瓶颈。

订阅者否认了消息

当订阅者否定确认(接收)消息时,它会向 Pub/Sub 表明无法成功处理该消息。然后,Pub/Sub 会尝试重新提交同一消息。对邮件反复进行反复缺失会导致重复,并可能导致邮件递送延迟较长的时间。

请注意,处理消息并不能保证下一次拉取会提取不同的消息。Pub/Sub 的重新提交政策可能会继续在发送新消息之前重新提交 NACK 消息。因此,请勿依赖 nacks 来过滤或跳过特定消息。相反,您可以设置重试政策(最好使用指数退避算法),以此来对以后可能可以处理但需要更长时间才能重新提交的个别邮件进行退避。

如果您需要故意跳过某些消息,建议的方法是确认这些消息,即使您不处理它们也是如此。这会从订阅中移除它们,避免不必要的重新提交,并减少资源消耗。消息未得到确认(无论是有意还是无意),会导致积压问题和重复递送。

传送延迟时间较长

Pub/Sub 中的传送延迟时间是指来自发布者的消息到达订阅者所需的时间。以下部分介绍了可能导致高传送延迟的一些原因。

订阅人数不足

对于使用 StreamingPull 的客户端,为了始终保持低延迟,请维护多个与您的订阅的开放的 StreamingPull 连接。如果没有活跃的订阅者连接,Pub/Sub 将无法及时传送消息。单个视频流可能会成为单点故障,增加了延迟风险。“subscription/open_streaming_pulls”指标可让您了解活跃的流式连接数。使用此设置可确保始终有足够的视频流来处理传入消息。

对于使用一元拉取的客户端,为了持续实现低延迟,请维护针对您的订阅的多个待处理拉取请求。不频繁的请求可能会积压积压消息,导致延迟时间增加。此方法有助于最大限度地减少连接间隙并缩短交付延迟时间。

如果您需要高吞吐量和低延迟,且运营开销和处理成本极低,则建议您使用高级客户端库。默认情况下,高级客户端库使用 StreamingPull API,因为在尽可能缩短延迟时间方面,它往往是更好的选择。高级客户端库包含预构建的函数和类,用于处理身份验证、吞吐量和延迟时间优化、消息格式设置及其他功能的底层 API 调用。

客户端配置问题

请参阅客户端配置问题

积压高

请注意,Pub/Sub 订阅中未确认的消息积压本身会增加端到端延迟时间,因为订阅者不会立即处理消息。

订购键和仅传送一次

订购键和“正好一次”传送是有价值的功能,但它们需要在 Pub/Sub 中进行额外的协调,以确保正确传送。这种协调会降低可用性并增加延迟时间。虽然在稳定状态下差异很小,但任何必要的协调步骤都可能导致延迟时间暂时增加或错误率增加。如果启用了排序功能,则具有排序键的消息无法传送,直到具有相同排序键的消息得到确认。

考虑对于您的应用来说,消息排序还是仅传送一次。如果您的首要任务是低延迟,尽量减少使用这些功能可能有助于减少邮件处理延迟。

邮件大小增加

消息大小突然增加可能会增加 Pub/Sub 与客户端之间的传输时间,并减慢客户端处理消息的时间。

如果您发现传送延迟时间增加,可以使用 topic/message_sizes 指标按 topic_id 分组来检查消息大小。将任何邮件大小高峰与观察到的性能问题相关联。

丢失的邮件

如果您怀疑消息未成功传送给订阅者, 以下原因之一可能是导致这种情况的原因之一。

具有多个使用方的 Pub/Sub 订阅中的消息分布

在 Pub/Sub 中,消息在使用方之间分布可能不均匀。出现这种行为是因为 Pub/Sub 在活跃使用方之间分发消息以提高效率。有时,单个使用者收到的消息可能少于预期,或者收到的消息子集不同于其他使用者。

请注意,消息可能已经对客户端未完成,积压的未确认消息并不一定意味着您将在下次拉取请求时收到这些消息。请注意,使用方可能是在 Google Cloud 控制台或 Google Cloud CLI 中使用拉取功能,或在本地运行自定义订阅者以检查消息的用户。

对于一元拉取客户端,您可能会发现一些拉取请求返回零消息。如订阅者数量不足部分所述,建议维护多个未完成的拉取请求,因为某些请求可能返回少于配置的最大消息数,甚至可能返回零消息。

如果您怀疑任何此类行为,请调查是否有多个消费者同时附加到订阅并检查。

按订阅过滤

检查相应订阅是否附加了过滤器。如果是这样,您只会收到与过滤器匹配的邮件。Pub/Sub 服务会自动确认与过滤条件不匹配的消息。考虑过滤条件如何影响积压指标

使用 returnImmediately 选项

如果您的客户端使用一元拉取,请检查 returnImmediately 字段是否设置为 true。这是一个已弃用的字段,该字段会指示 Pub/Sub 服务立即响应拉取请求,即使它返回时没有任何消息也是如此。这可能导致拉取请求返回 0 条消息,即使出现积压也是如此。

处理重复内容

当订阅者无法在确认时限内确认消息时,Pub/Sub 中通常会出现消息重复。这会导致邮件被重新提交,造成重复内容展示。您可以使用 subscription/expired_ack_deadlines_count 指标衡量订阅者错过确认时限的比率。详细了解如何监控确认截止期限

为降低重复率,请延长消息的截止时间。

  • 客户端库会自动处理截止期限延长,但您可以配置的最大延长期限有默认限制。
  • 如果您要构建自己的客户端库,请使用 modifyAckDeadline 方法延长确认时限。

如果从订阅者中拉取消息的速度比处理和确认消息的速度快,有些消息可能会过期,并且需要延长期限。但是,如果订阅者仍然不堪重负,重复的截止期限延长最终会失败。在最糟糕的情况下,这可能会导致订阅者大量重复,加剧积压输入量。过期重复项随后会生成新的重复项。

为避免订阅者感到应接不暇,请减少订阅者一次拉取的消息数量。这样,订阅者在截止期限内要处理的消息就会减少。过期的消息越少,重新提交的消息也就越少。

要减少订阅者每次拉取的消息数量,您需要在订阅者的流控制配置中降低未完成消息数量上限。没有放之四海而皆准的值,因此您必须根据吞吐量和订阅者容量调整未完成消息的数量上限。假设每个应用处理消息的方式不同,确认消息所花费的时间也不同。

强制重试

如需强制 Pub/Sub 重试消息,请发送 nack 请求。如果您使用的不是高级客户端库,请发送 modifyAckDeadline 请求,并将 ackDeadlineSeconds 设置为 0。

排序键

当 Pub/Sub 重新提交包含 ordering 键,也会重新提交所有后续的 带有相同排序键的消息,即使之前已确认它们也是如此。 这样做是为了保持序列的顺序。不过,我们没有严格的 可以保证在成功发送成功请求后, 序列中先前消息的确认。

订阅方正在接收消息

请参阅订阅者正在接收消息

StreamingPull 订阅问题排查

StreamingPull 流始终以不正常状态关闭。取消采用错误状态 对于一元 RPC,此 StreamingPull 状态仅表示 视频流断开连接请求未失败。因此,虽然 StreamingPull API 错误率可能高达 100%, 设计。

由于 StreamingPull 流始终以错误关闭,因此 在诊断错误时检查数据流终止指标。而应专注于 StreamingPull 响应指标 subscription/streaming_pull_response_count, 按 response_coderesponse_class 分组。

请查找以下错误:

  • 如果 使用已停用的 Cloud KMS 密钥加密的订阅积压消息。接收者 恢复拉取、恢复对密钥的访问权限

  • 当 Pub/Sub 无法执行以下操作时,可能会发生不可用错误: 处理请求这很可能是一种暂时情况, 会重试请求如果您符合以下情况,则无需采取任何行动 使用客户端库

  • 删除订阅或从未删除订阅时,可能会发生“未找到”错误 它的存在如果您提供的是无效的 订阅路径。