2015-09-22 102 views
0

想象一下,每個用戶都有自己的隊列。當用戶離線時,郵件會被放入隊列中,當他們重新連接時,郵件會收到所有這些郵件。RabbitMQ:如果消費者永遠消失,請刪除一個隊列?

但是,如果客戶端離開並永不回來(停止使用該服務)會怎麼樣?如果消息在一段時間內沒有被消費,RabbitMQ是否有辦法刪除一個隊列?消息可能會進入,但它們不會熄滅,因爲客戶端不再處於活動狀態。我怎樣才能用amqp.node插件處理這個問題?

回答

1

試想每個用戶都有自己的隊列。當用戶離線時,郵件會被放入隊列中,當他們重新連接時,郵件會收到所有這些郵件。

這是一個普遍的想法,但one with unfortunate consequences, that you should avoid

,因爲我是掛在文章中寫道:

您可能會解決此通過在每個用戶的隊列。您 可能會設置您的代碼,以便Web服務器僅在用戶登錄且可用時爲用戶訂閱 隊列。

這並不能解決問題。

現在,您已經有30000條消息分佈在1000個隊列中 - 其本身就是一個不好的 情況。這需要RabbitMQ在隊列中保留隊列和消息。當所有1,000個用戶同時登錄到您的系統時會發生什麼?現在您的Web服務器有1000 隊列訂閱來處理。

當然,你可能會爭辯說,你不會有那麼多的用戶。但情況變得更糟。在你的情況下,你將無法自動地以你想要的方式刪除隊列。

您可以設置一個隊列,在所有使用者斷開連接後自動刪除。但保持隊列將需要每個用戶隊列的消費者,消費者在該用戶存在時連接到該隊列。如果應用程序崩潰,則隊列及其所有消息都將消失。

TTL只會做你想要的一部分。它會在隊列中放置一條消息並在該超時之後刪除該消息...但它不會刪除該隊列。

最終,你不想用RabbitMQ做到這一點。

再次

,從my article on the subject

再回到原來的情況下,當 用戶不在線,你不能立即將消息發送到他們應該怎麼做?

將消息存儲在數據庫中。

將一個字段添加到數據庫記錄中,該字段說明此消息的來源爲 。當用戶稍後重新連接時,請查詢數據庫以獲取該用戶此時需要查看併發送的任何 消息。

全過程上面開始,然後變成這樣:

  • 用戶的瀏覽器連接到SignalR/Socket.io /子彈頭/ WebSockets的網絡上服務器
  • Web服務器檢查隊列的過程中所發生的更新長 運行的進程
  • 當如果 用戶爲LO一個登錄用戶進來
    • 消息gged中,廣播通過WebSocket的消息給 用戶
    • 如果用戶沒有登錄,存儲信息的數據庫
  • 當用戶再次登錄,查詢數據庫,並把所有的等待 消息

這就是你會做一個消息隊列 的想法來之前在玩,對吧?它應該是你現在要做的事,即你有一個消息隊列。

+0

這並不回答我的問題,但它回答了「我該如何處理我想要做的事情?」的問題。所以我接受了它。你是對的!我最初使用數據庫來存儲這些消息,但發現RabbitMQ,並認爲它幾乎是一個錯誤的「消息數據庫」。謝謝你打開我的眼睛!儘管問題很快......您對於存儲這些信息的數據庫的建議是什麼? –

+0

是的,我希望回答這個意圖,而不是真正的問題會更有價值:D至於什麼數據庫使用?你通常使用什麼?你的應用/系統中已經有了什麼數據庫?堅持你所知道的數據庫。 –

+0

我想我們將使用Redis列表。 O(1)插入和「流行」功能非常棒。我正在考慮彈出redis列表中的值並通過網絡套接字發送消息。我正在尋找「全部彈出」功能,但「彈出時不返回空」是另一種選擇。 –