本文档提供了一些常见的 Pub/Sub 拉取订阅问题排查提示。如需详细了解拉取订阅,请参阅拉取订阅者指南。
为了有效监控 Pub/Sub 订阅,建议您先查看传送延迟时间运行状况得分 (subscription/delivery_latency_health_score),检查哪些因素会导致延迟时间意外增加或增加。
最早的未确认消息的存在时间不断增加
oldest_unacked_message_age
是监控 Pub/Sub 订阅运行状况的重要指标。它测量订阅积压中尚未被订阅者确认(确认)的最旧消息的存在时间(以秒为单位)。此指标可提供有价值的数据洞见,帮助您了解潜在的处理延迟或瓶颈。
监控消息积压可确保及时高效地处理消息。通过跟踪最早的未确认消息的存在时长,您可以主动发现消费者未及时确认消息的情况。这种做法有助于及早进行干预,解决与表现下降相关的潜在问题。
您可以调查的一些积压常见问题包括:
客户端配置问题
当 oldest_unacked_message_age
和 num_undelivered_messages
指标同时增加时,可能意味着订阅者未跟上消息量。在这种情况下,请将调查重点放在订阅者组件上:
客户端运行状况:分析托管订阅方客户端的计算机上的资源利用率,例如 CPU、内存和网络带宽。找出可能影响处理效率的压力点。
客户端代码:查看近期的代码更改并检查错误日志。订阅者代码中的 bug 或效率低下可能会显著影响消息处理速率。请注意,特定消息中可能存在问题。例如,多条消息可能需要同时访问数据库中的同一行。此行为可能导致争用和高延迟。
配额限制:请检查您是否超出了任何 Pub/Sub 配额或托管服务施加的限制。如果订阅者托管在 Google Cloud 中,请查看 Compute Engine 或 GKE 资源配额,以防止出现潜在瓶颈。
订阅者对消息发出了否定确认
当订阅者拒绝(接受)某条消息时,它会向 Pub/Sub 表明无法成功处理该消息。然后,Pub/Sub 会尝试重新传送同一消息。对邮件反复进行反复缺失会导致重复,并可能延长邮件传送的延迟时间。
请注意,取消订阅消息并不能保证下次拉取会提取其他消息。Pub/Sub 的重新传送政策可能会继续在有新消息之前重新传送未封装的消息。因此,请勿依赖 nack 来过滤或跳过特定消息。相反,您可以设置重试政策(最好使用指数退避算法),以便对以后可能可以处理但需要更长时间才能重新提交的个别邮件进行退避。
如果您需要有意跳过某些消息,建议的方法是确认收到这些消息,即使您不会处理这些消息也是如此。这会从订阅中移除它们,避免不必要的重新提交,并减少资源消耗。消息未得到确认(无论是有意还是无意),会导致积压问题和重复递送。
传送延迟时间较长
Pub/Sub 中的传送延迟时间是指来自发布者的消息到达订阅者所需的时间。以下部分介绍了导致传送延迟时间较长的一些可能原因。
订阅者数量不足
对于使用 StreamingPull 的客户端,为了始终保持低延迟,请维护多个与您的订阅的开放 StreamingPull 连接。如果没有活跃的订阅者连接,Pub/Sub 将无法及时传送消息。单个视频流可能会成为单点故障,增加了延迟风险。“subscription/open_streaming_pulls
”指标可让您了解活跃的流式连接数。使用此方法可确保您始终有足够的串流来处理传入的消息。
对于使用单个拉取操作的客户端,为了始终保持较低的延迟时间,请针对您的订阅维持多个待处理的拉取请求。请求不频繁可能会导致积压消息并增加延迟时间。此方法有助于最大限度地减少连接间隙并缩短交付延迟时间。
如果您需要高吞吐量和低延迟时间,同时尽可能减少运营开销和处理费用,建议使用高级客户端库。默认情况下,高级客户端库使用 StreamingPull API,因为在尽可能缩短延迟时间方面,它往往是更好的选择。高级客户端库包含预构建的函数和类,用于处理身份验证、吞吐量和延迟时间优化、消息格式设置及其他功能的底层 API 调用。
客户端配置问题
请参阅客户端配置问题。
积压高
请注意,Pub/Sub 订阅中未确认消息的消息积压会固有地增加端到端延迟时间,因为订阅者不会立即处理消息。
订购键和仅传送一次
排序键和“恰好一次”传送是十分有用的功能,但需要在 Pub/Sub 中进行额外的协调,以确保正确传送。这种协调可能会降低可用性并增加延迟时间。虽然在稳定状态下差异很小,但任何必要的协调步骤都可能会导致延迟时间暂时增加或错误率增加。如果启用了排序功能,则具有排序键的消息无法传送,直到具有相同排序键的消息得到确认。
考虑消息排序或“正好一次”传送是否对您的应用至关重要。如果您最看重低延迟,尽量减少使用这些功能有助于缩短消息处理延迟时间。
增加消息大小
消息大小突然增加可能会增加 Pub/Sub 与客户端之间的传输时间,并减慢客户端处理消息的时间。
如果您发现传送延迟时间增加,可以使用按 topic_id
分组的 topic/message_sizes
指标来检查消息大小。将消息大小的任何激增与观察到的性能问题相关联。
丢失的邮件
如果您怀疑消息未成功传送给订阅者, 以下原因之一可能是导致这种情况的原因之一。
具有多个使用方的 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 重新传送带有排序键的消息时,它也会重新传送具有相同排序键的所有后续消息,即使这些消息之前已确认也是如此。这样做是为了保持序列的顺序。不过,我们无法严格保证,系统只会在序列中之前的消息成功确认后发送依赖消息。
订阅者正在取消订阅消息
请参阅订阅者正在接收消息。
StreamingPull 订阅问题排查
请求延迟时间指标与端到端传送延迟时间之间的关系
对于 StreamingPull,指标 serviceruntime.googleapis.com/api/request_latencies 表示数据流处于打开状态的时间。该指标对确定端到端传送延迟时间没有帮助。
您可以使用传送延迟时间运行状况得分(而非请求延迟时间指标)来查看哪些因素导致端到端传送延迟时间增加。
StreamingPull 连接以非正常状态关闭
StreamingPull 流始终以不正常状态关闭。取消采用错误状态 对于一元 RPC,此 StreamingPull 状态仅表示 视频流断开连接请求未失败。因此,虽然 StreamingPull API 错误率可能高达 100%, 设计。
由于 StreamingPull 流始终以错误关闭,因此
在诊断错误时检查数据流终止指标。不妨关注 StreamingPull 响应指标 subscription/streaming_pull_response_count
,按 response_code
或 response_class
分组。
请查找以下错误:
不满足前提条件如果 使用已停用的 Cloud KMS 密钥加密的订阅积压消息。接收者 恢复拉取、恢复对密钥的访问权限。
当 Pub/Sub 无法处理请求时,可能会发生不可用错误。这很可能是一种暂时性情况,客户端库会重试请求。如果您符合以下情况,则无需采取任何行动 使用客户端库
如果订阅已被删除或从未存在,则可能会出现“未找到”错误。如果您提供的是无效的 订阅路径。