2017-03-24 100 views
0

我想要一個簡單的任務隊列。將有多個使用者在不同的機器上運行,但我只希望每個任務消耗一次。使用Google 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

總之,是的,有一些機會,一些消息將被複制:GCP承諾至少交付一次。在任何分佈式系統中,一次交付在理論上是不可能的。你應該設計你的doSomethingWith代碼,如果可能的話是冪等的,所以重複的消息不是問題。

一旦完成處理,您也應該只確認一條消息:如果您的機器在acknowledge之後但在doSomethingWith返回之前死亡,會發生什麼情況?你的信息將會丟失! (這個基本思想就是爲什麼 - 一旦交付是不可能的)。

如果丟失的消息是最好的兩倍處理它們,你可以添加一個鎖定過程(寫有「處理」令牌一致的數據庫),但如果處理消息之前寫是這樣處理可能會失敗。但是在這一點上,您可能會找到一種專爲最多一次設計的消息傳遞技術,而不是針對可靠性進行優化。