使用Google PubSub的作业队列

时间:2017-03-24 17:35:15

标签: google-cloud-pubsub

我想要一个简单的任务队列。将有多个消费者在不同的机器上运行,但我只希望每个任务都被消耗一次。

如果我有多个订阅者使用相同的订阅ID从某个主题接收消息,那么该消息是否有可能被读取两次? 我已成功测试了这些内容,但我担心可能存在同步问题。

client = SubscriberClient.create(SubscriberSettings.defaultBuilder().build());
subName = SubscriptionName.create(projectId, "Queue");
client.createSubscription(subName, topicName, PushConfig.getDefaultInstance(), 0);

Thread subscriber = new Thread() { 
  public void run() {
    while (!interrupted()) {
      PullResponse response = subscriberClient.pull(subscriptionName, false, 1);
      List<ReceivedMessage> messages = response.getReceivedMessagesList();
      mess = messasges.get(0);
      client.acknowledge(subscriptionName, ImmutableList.of(mess.getAckId()));
      doSomethingWith(mess.getMessage().getData().toStringUtf8());
    }
  }
};
subscriber.start();

1 个答案:

答案 0 :(得分:3)

简而言之,是的,有些消息可能会被复制:GCP承诺至少一次交付。在任何分布式系统中,理论上都不可能完全一次交付。如果可能,您应该将doSomethingWith代码设计为幂等的,这样重复的消息就不是问题。

一旦完成处理,您也应该只收到一条消息:如果您的机器在acknowledge之后但doSomethingWith返回之前死亡,会发生什么?你的信息会丢失! (这个基本思想就是为什么一次交付是不可能的)。

如果丢失消息比对它们进行双重处理更好,则可以添加一个锁定进程(将#34;已处理的&#34;令牌写入一致的数据库),但如果在消息之前处理写入,则可能会失败处理。但此时您可能会找到一种最常设计的消息传递技术,而不是针对可靠性进行优化。