首页 > 解决方案 > Google PubSub 和来自 TOPIC 的重复消息

问题描述

如何防止 Google Cloud PubSub 中发生重复的 msg?

说,我有一个处理它订阅的味精的代码。

说,我有 2 个节点具有相同的服务,具有此代码。

一旦一个人收到了消息但尚未确认,另一个节点将收到相同的消息。这就是我们有两个重复的 msgs的问题所在。

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();
    }

解决方案是什么?这是正常行为吗?

标签: javagoogle-cloud-platformgoogle-cloud-pubsub

解决方案


Google Cloud Pub/Sub 使用“至少一次”交付。从文档

通常,Cloud Pub/Sub 会按照发布的顺序交付每条消息一次。但是,有时可能会乱序或多次传递消息。通常,容纳多次传递要求您的订阅者在处理消息时是幂等的。

这意味着它保证它将以 1:N 的方式传递消息,因此如果您不通过其他方式首先对其进行重复数据删除,则您可能会多次获取该消息。您无法定义一个设置来保证一次交付。文档确实引用了您可以使用 Cloud Dataflow 获得所需的行为PubSubIO,但该解决方案似乎已被弃用

您可以使用 Cloud Dataflow 实现对 Cloud Pub/Sub 消息流的一次性处理PubsubIO。PubsubIO 对自定义消息标识符或 Cloud Pub/Sub 分配的消息进行重复数据删除。

说了这么多,我实际上从未见过 Google Cloud Pub/Sub 两次发送消息。您确定这确实是您遇到的问题,还是因为您没有在确认截止日期内确认消息而重新发出消息(如上所述,这默认为 10 秒)。如果您不承认,它将重新发布。从文档 (强调我的)

为单个主题创建订阅。它有几个属性可以在创建时设置或稍后更新,包括:

  • 确认截止日期:如果您的代码在截止日期之前未确认消息,则会再次发送消息。默认值为 10 秒。您可以指定的最大自定义期限为 600 秒(10 分钟)。

如果是这种情况,只需在截止日期内确认您的消息,您就不会经常看到这些重复的消息。


推荐阅读