异步订阅者示例会丢失消息吗?

时间:2019-08-02 23:39:20

标签: google-cloud-pubsub

从pubsub开始。在阅读Google Cloud文档时,我遇到了一段代码,并且我认为示例存在缺陷。

这是我正在谈论的代码。它使用异步订阅者。

public class SubscriberExample {

  private static final String PROJECT_ID = ServiceOptions.getDefaultProjectId();

  private static final BlockingQueue<PubsubMessage> messages = new LinkedBlockingDeque<>();

  static class MessageReceiverExample implements MessageReceiver {

    @Override
    public void receiveMessage(PubsubMessage message, AckReplyConsumer consumer) {
      messages.offer(message);
      consumer.ack();
    }
  }

  public static void main(String... args) throws Exception {
    String subscriptionId = args[0];
    ProjectSubscriptionName subscriptionName = ProjectSubscriptionName.of(
        PROJECT_ID, subscriptionId);
    Subscriber subscriber = null;
    try {
      subscriber =
          Subscriber.newBuilder(subscriptionName, new MessageReceiverExample()).build();
      subscriber.startAsync().awaitRunning();
      while (true) {
        PubsubMessage message = messages.take();
        processMessage(message);
      }
    } finally {
      if (subscriber != null) {
        subscriber.stopAsync();
      }
    }
  }

我的问题是,如果一堆消息已经被确认,并且BlockingQueue不为空,并且服务器崩溃,该怎么办?那我会丢失一些消息吧? (已在PubSub中确认,但未实际处理。)

最好的实现方法是只在处理完消息后才确认消息吗?而不是确认它并将其留在队列中,并假定将对其进行处理。我知道这将使消息的接收与消息的处理脱钩,并可能提高吞吐量,但仍然有丢失消息的风险,对吗?

1 个答案:

答案 0 :(得分:0)

是的,只有在消息完全处理后,您才应该确认消息。否则,可能永远无法处理该消息,因为如果发生确认,它不会在崩溃或重新启动时重新传递。我有entered an issue来更新示例。