2011-11-27 113 views
4

我正在嘗試編寫使用JMS發佈訂閱模型的應用程序。不過,我遇到了挫折,我希望能夠讓發佈商從主題中刪除消息。用例是我擁有持久訂閱者,活躍訂閱者會得到這些消息(因爲它或多或少是即時的),但是如果存在不活動的消息並且發佈者決定消息是錯誤的,我希望讓他能夠刪除消息以便用戶一旦活動就不會再收到它。 問題是,我不知道如何做到這一點。 對於一家供應商我決定使用glassfish的實現,但如果其他替代方案提供此功能,我可以切換。如何從主題中刪除郵件

謝謝。

回答

6

JMS是異步消息傳遞的一種形式,因此發佈者和訂閱者通過設計分離。這意味着沒有機制去做你正在問的東西。對於在發佈時處於活動狀態的訂閱者,他們將消費該消息而沒有及時收到刪除消息的機會來處理它。如果用戶不在線,那麼他們會認爲異步消息是原子的。如果您繼續設計其他受訪者的答案(創建刪除消息並要求重新連接消費者以讀取整個隊列以查找刪除消息),那麼您將創建一種情況,其中系統的行爲會根據訂閱者是否有所不同在發佈特定消息/刪除組合時已上線或未上線。在發佈者發出刪除消息之前,用戶還完成讀取保留消息的競爭條件。這意味着您必須向訂閱者提供重要的邏輯來協調這些條件,甚至更好地協調競爭條件。

這樣做的接受方法是所謂的「補償交易」。在生產者和消費者不共享單個工作單元或共享共同狀態的任何系統中(例如使用相同的DB來存儲狀態),則退出或更正以前的事務需要第二次事務處理,即第一次事務處理。消費者當然必須能夠正確地應用補償交易。當使用這種模式時,結果是所有訂戶都表現出相同的行爲,無論消費者重新啓動後消息是實時還是批量消費。

請注意,補償交易與「刪除消息」不同。另一個答覆者答案中提出的刪除消息是一種影響消息流本身的命令和控制形式。另一方面,補償事務通過事務更新系統狀態來影響系統的狀態。

作爲一般規則,你從來沒有想通過操縱帶有命令和控制功能的消息流來管理系統的狀態。這是脆弱的,容易受到攻擊,很難審計或調試。相反,請設計系統以傳遞受其服務質量約束的每封郵件並處理所有郵件。完全在應用程序中處理狀態更改(包括反轉之前的操作)。

作爲一個例子,在銀行業務中,交易觸發輔助效果,例如透支費用,通常的做法是在白天「備忘」交易,然後在銀行關閉後對其進行分批處理和批量應用。這使得在之前出現的錯誤可能會導致透支費用。最近,這些交易是實時應用的,但觸發器被扣留,直到當天的賬單結束,並且達到相同的結果。

+0

+1,閱讀您的答案總是很高興。 – MaDa

+0

謝謝,爲客氣話! –

-1

您必須讓製作人發送delete消息,消費者需要在開始處理消息之前閱讀所有消息。

+0

謝謝,這意味着我必須照顧這部分的完整實施,但這也意味着訂戶將看到已刪除的消息,但基本上忽略它。有沒有辦法阻止消息到達他? – LuBa

+0

你可以自己有過期的消息。 –

1

JMS API不允許從任何目標(隊列或主題)中刪除消息。儘管我相信特定的JMX提供者提供了他們自己的專有工具來管理他們的狀態,例如使用JMX。儘量檢查出你的JMS提供者,但要小心:即使你找到解決方案,它也不能在不同的JMS提供者之間移植。

「刪除」消息的一種合法方式是使用其生存時間: publish(Topic topic, Message message, int deliveryMode, int priority, long timeToLive)。對你來說可能是夠好的了。

如果它不適用於您的應用程序,請在應用程序級別解決問題。例如,將唯一ID附加到每條消息,併發布具有更高優先級的特殊「刪除」消息,這將是一種刪除具有相同ID的「真實」消息的命令。