2011-06-14 90 views
3

我們有一個持久的RabbitMQ隊列。當消費者從隊列中獲取物品時,會對其進行處理,然後對其進行確認。如果消費者未能處理該項目,則會輸出一個錯誤,指示某人解決問題並停止。沒有確認正在發送。消費者重新啓動時,它收到的物品是隊列中的下一個物品,而不是沒有確認物品。 Basic.Recover()沒有幫助(使用.NET客戶端)。 任何想法如何使它作爲一個隊列工作 - 總是得到第一個項目,如果它不是acked。RabbitMQ Basic恢復不起作用

回答

3

this entry in the RabbitMQ FAQ。雖然您可能希望RabbitMQ重新將未發送的消息重新排列到隊列頭部(在消費者拉下它們之前的位置),但實際情況可能會與您經歷的不同。

所以不是Basic.Recover()不起作用(消息放回隊列以備將來再處理),只是它不能按照您的預期方式工作。

東西在我的腦海裏告訴我,你可能能夠通過設置爲1的預取計數和具有至多隻有一個消費者連接到隊列隨時得到你想要的行爲,但我不能保證是這種情況。值得嘗試。然而,即使它有效,它也不會依賴永久保留這種情況,並且如此低的預取次數,您的消費者的消息/秒性能可能會受到影響。

+0

我的計劃是將預取計數設置爲1,將失敗的消息序列化爲一個文件並確認它。當一個進程再次啓動時,它會從該文件獲取第一條消息,對其進行處理,然後繼續使用隊列。 – Kimi 2011-06-15 09:39:37

+1

如果某個進程被終止,這不起作用。無論如何,兔子會把它放到隊尾。 – Kimi 2011-06-16 08:21:37

2

消息可以以兩種方式被消耗NOACK =假或NOACK =真

NOACK是在兩個Model.BasicConsume和Model.BasicGet

參數

當NOACK設置爲true信息將自動從除去交付後的隊列。如果noAsk設置爲false,則只有在調用basicAck時纔會刪除消息。

如果諾亞克=假,你不叫basicAck消息將保留,但要等到重新啓動應用程序,您將不會收到對其他消費者(或關閉,首先消耗的是連接)。如果您調用BasicReject,則消息將被重新發送給訂閱者。

我希望這會有所幫助。

+0

你或許應該改變上面「諾亞克」,而不是你的許多「noAsk」的例子。 – 2011-06-14 22:35:54

0

您可以通過具有一對隊列,一個高優先級和一個正常優先級得到這個行爲。將預取計數設置爲1,然後使用basic.get在隊列之間交替。大多數情況下,優先級隊列將爲空,但是當您想要重新排隊時,請將該消息再次發佈到高優先級隊列上。

這工作在你有多個進程消耗的消息流的情況下,和一個進程決定保釋出來的消息。這個消息幾乎立即被另一個進程拾取。

+0

我的場景非常簡單 - 有一個消費者,消息的順序非常重要,如果發生意外關閉(電源故障),RabbitMQ會將隊列的第一條消息放到隊列的末尾。所以我想我應該使用其他經紀人先保留第一條消息,直到客戶將其出列。 – Kimi 2011-06-16 08:19:26

+0

我在這裏問了一個更相關的問題http://stackoverflow.com/questions/6369190/what-open-source-message-queuing-software-provides-durability-with-strict-orderin – Kimi 2011-06-16 08:44:38

1

的RabbitMQ似乎已經解決了這個問題since 2.7.0的一部分,因爲現在消息將在公佈的順序重新排隊。雖然如果您有多個訂閱者加入隊列,您仍可能會收到來自原始訂單的消息。