我有一个问题,这发生在我的系统周期性,但导致重大问题。
我们使用GCP Pub/Sub,有时订阅者会收到恰好1分钟延迟的消息。在这些情况下,只有以下指标真正达到峰值:
1.最早未确认消息年龄
- delivery_latency_health_score.expired_ack_deadlines = 0
1.过期确认期限计数
以下是我订阅的详细信息:subscription details
备注:
1.指标unacked_messages_count不会被激增,因此系统的负载通常是。
1.我确信延迟的消息在Pub/Sub中被成功发布,并且我看到了它们正确的publish_time属性。
1.通过所有其他指标,我可以看到,系统并没有过载,用户继续拉其他消息。
1.我在订阅服务器中开始消息处理后立即打印日志,这就是我看到延迟的原因。
我们正在使用google-cloud-pubsub、spring-cloud-gcp-pubsub、proto-google-cloud-pubsub-v1和spring-integrations客户端库来StreamingPull消息。我们为此使用gRPC协议。
我假设消息有时会由于瞬时故障而丢失,但在这种情况下,它们应该在10秒内重新发送,基于我的确认截止日期,不是吗?**更新:**在message上,它带有60秒延迟我发现了一个属性googclient_deliveryattempt=1
。据我所知,这意味着它不是重新发送?
我也认为问题可能是在modifyAckDeadline请求,但我没有任何自定义覆盖.并且我看到我的客户端库默认使用DEFAULT_MAX_ACK_EXTENSION_PERIOD = 0.更新:然而,我们发送一个StreamingPullRequest与StreamAckDeadlineSeconds = 60,因为这个值是用STREAM_ACK_DEADLINE_DEFAULT初始化的,这是60在客户端库.但是StreamingPullRequest中的注解说:“我们需要设置流确认的截止日期,但这是没有用的,因为我们将modack发送收据。设置为一些大的值,以防我们modack晚”。
我希望订阅者可以在发布后立即收到消息,或者如果有失败/丢失,消息将在10-20秒后重新发送,而不是60秒。
有什么建议可以解决这个问题吗?
1条答案
按热度按时间fnatzsnv1#
Spring库使用Pub/Sub客户端库,它覆盖了订阅中指定的ack deadline并实现了自己的lease management。默认情况下,初始ack deadline是60秒,这可能就是为什么你会看到一些消息延迟60秒。可能发生的情况是,最后期限在开始时设置为60秒,然后消息从服务器,但是客户端在消息被处理之前重新启动。在这种情况下,消息将在60秒内不会被重新传递。
如果你想将这个时间减少到10秒,你需要更改每个确认扩展的最大持续时间。当直接使用Java客户端库时,在构建器中调用
setMaxDurationperAckExtension()
。如果使用Spring订阅者配置,设置spring.cloud.gcp.pubsub.subscriber.max-duration-per-ack-extension
。