如何防止 Google Cloud PubSub 中发生重复消息?
比如说,我有一个处理它所订阅的消息的代码。
假设我有 2 个节点,它们的服务具有相同的代码。
一旦一个节点收到消息但尚未确认,另一个节点将收到相同的消息。这就是问题所在,我们有两个重复的消息.
void messageReceiver(PubsubMessage pubsubMessage, AckReplyConsumer ackReply) {
submitHandler.handle(toMessage(pubsubMessage))
.doOnSuccess((response) -> {
log.info("Acknowledging the successfully processed message id: {}, response {}", pubsubMessage.getMessageId(), response);
ackReply.ack(); // <---- acknowledged
})
.doOnError((e) -> {
log.error("Not acknowledging due to an exception", e);
ackReply.nack();
})
.doOnTerminate(span::finish)
.subscribe();
}
对此有什么解决办法吗?这是正常行为吗?
Google Cloud Pub/Sub 使用“至少一次”交付。从the docs:
通常,Cloud Pub/Sub 会按消息发布的顺序传递每条消息一次。然而,消息有时可能会无序传送或多次传送。一般来说,要满足多次交付要求您的订户幂等的处理消息时。
这意味着它保证将以 1:N 的方式传递消息,因此,如果您不首先通过其他方式对其进行重复数据删除,则可能会多次获取该消息。您无法定义任何设置来保证恰好一次传送。该文档确实提到您可以使用 Cloud Dataflow 获得您想要的行为PubSubIO
, but 该解决方案似乎已被弃用:
您可以使用 Cloud Dataflow 实现 Cloud Pub/Sub 消息流的一次性处理PubsubIO。 PubsubIO 可对自定义消息标识符或由 Cloud Pub/Sub 分配的消息进行重复消息删除。
说这一切,我从来没有actually看到 Google Cloud Pub/Sub 发送了两次消息。您确定这确实是您遇到的问题吗?还是因为您没有在确认截止期限(如上所述,默认为 10 秒)内确认该消息,所以该消息被重新发出。如果您不承认,它将重新发布。从the docs (强调我的):
为单个主题创建订阅。它有几个属性可以在创建时设置或稍后更新,包括:
- An 确认期限: 如果您的代码在截止日期之前未确认该消息,则会再次发送该消息。默认值为 10 秒。您可以指定的最大自定义截止时间为 600 秒(10 分钟)。
如果是这种情况,只需在截止日期内确认您的消息,您就不会经常看到这些重复内容。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)