订阅者永远不会得到整个队列

Subscriber never gets the entire queue

我们正在与 PubSub 合作,将多个系统相互集成。一些系统可能将数据作为 JSON 推送到 PubSub,而其他系统可以拉取该数据并使用它。 (注意:由于接收应用程序的其他限制,我们必须从 PubSub 拉取而不是推送到应用程序)每个拉取应用程序都有自己的订阅者到每个主题。

我注意到,如果触发过于频繁,PubSub 拉取不会获取队列中当前的所有数据。该问题最初出现在具有相应库的 Java Spring 应用程序中,但云控制台中的 gcloud 命令表现出相同的行为,因此我将使用该示例。我删除了 ack-ids 和边框以使其适合这个 window。请注意我如何不使用“--auto-ack”标志,因此队列应该保持不变,没有其他系统从该订阅者那里拉取。

先拉(完整内容): max_binnewies@cloudshell:~ $ gcloud pubsub subscriptions pull testSubscriber --limit=100

│    DATA   │    MESSAGE_ID   │ 
│ 4 - FOUR  │ 189640873208084 │
│ 5 - FIVE  │ 189636274179799 │ 
│ 2 - TWO   │ 189638666587304 │ 
│ 3 - THREE │ 189627470480903 │  
│ 1 - ONE   │ 189639207684195 │

二拉(只有一个): max_binnewies@cloudshell:~ $ gcloud pubsub subscriptions pull testSubscriber --limit=100

│   DATA  │    MESSAGE_ID   │
│ 1 - ONE │ 189639207684195 │

第三拉(两个不同的): max_binnewies@cloudshell:~ $ gcloud pubsub subscriptions pull testSubscriber --limit=100

│   DATA   │    MESSAGE_ID   │ 
│ 4 - FOUR │ 189640873208084 │ 
│ 5 - FIVE │ 189636274179799 │

第四次拉(又是第一次): max_binnewies@cloudshell:~ $ gcloud pubsub subscriptions pull testSubscriber --limit=100

│   DATA  │    MESSAGE_ID   │
│ 1 - ONE │ 189639207684195 │

这种行为让我感到困惑。这是正常的 PubSub 行为还是我做错了什么?我唯一发现的是这个 link ,它说 PubSub 使用 pull 方法的负载平衡: https://cloud.google.com/pubsub/docs/subscriber 因此,我认为订阅者认为多个客户端正在订阅它,如果来电太快,就会分散数据。那是对的吗?这里到底发生了什么? 如果我稍等片刻,我会再次获得更多数据,但即使我等了五分钟,我似乎也从未获得过所有数据……这非常令人困惑。 这会给消费应用程序带来问题吗?我如何确保所有数据都到达接收应用程序,即使它拉得非常频繁?有没有办法关闭它?

有几件事导致您每次都没有收到所有消息:

  1. 对于拉取请求,无法保证所有消息都将在特定请求中返回,即使可用消息数少于最大消息数也是如此。这是因为 Pub/Sub 试图在返回更多消息与最小化端到端延迟之间取得平衡。

  2. 消息有一个确认期限,它在订阅创建时指定(默认为 10 秒)。这意味着当您拉取消息并且不确认或拒绝它们时,它们将不会在 ack 截止期限内重新传送,基本上是给拉取消息的进程租用它们。如果您希望立即重新传送消息,您需要 nack them if you are using the Java client library (the preferred way to interact with Cloud Pub/Sub) or you need to send a ModifyAckDeadline 请求并将 ack_deadline_seconds 设置为 0。