2012-07-15 118 views
2

我有一個由第三方發佈的JMS隊列。 我想在不同的機器上設置多個使用者,只有一臺特定的機器使用者,確認該隊列上的消息。簡而言之,如果特定機器的消費者沒有收到消息,那麼不應該從隊列中刪除該消息。 這是可以實現的嗎?JMS - 一個隊列和很多接收者(消費者)

+0

不知道是什麼原因,我想所有的消費者都必須收到消息,但只有一個特定的消費者會承認這個消息。如果情況並非如此,那麼爲什麼你想讓同一隊列中有多個消費者? – Shashi 2012-07-16 03:22:43

回答

1

好的,你可能有這個設置的原因,這很容易實現。

我會去與本地會話事務。根據某些標準提交或回滾事務是相當容易的,例如哪個服務器正在消費該消息。如果回滾,則消息將再次在隊列中首先結束。

示例代碼可能是這樣的:

public class MyConsumer implements MessageListener{ 
    Session sess; 

    public void init(Connection conn, Destination dest){ 
    // connection and destination from JNDI, or some other method. 
    sess = conn.createSession(true, Session.AUTO_ACKNOWLEDGE); 
    MessageConsumer cons = sess.createConsumer(dest); 
    cons.setMessageListener(this); 
    conn.start(); 
    } 

    @Override 
    public void onMessage(Message msg) { 
    // Do whatever with message 
    if(isThisTheSpecialServer()){ 
     sess.commit(); 
    }else{ 
     sess.rollback(); 
    } 
    } 

    private boolean isThisTheSpecialServer(){ 
     // figure out if this server should delete messages or not 
    } 
} 

如果您正在使用JTA在Java EE容器內這樣做的,你正在使用UserTransactions,你可以只調用UserTransaction.setRollBack(); 或者如果您正在使用聲明性事務,則只需讀取Runtime異常以使事務失敗並將消息回滾到隊列中,一旦您讀取了消息並完成了任務。請注意,使用這種方法數據庫更改也會回滾(如果您使用的是JTA而不是本地JMS事務)。

UPDATE:

你真的應該做到這一點使用的交易,而不是確認。

在這裏可以找到該主題的摘要(對於ActiveMQ,但通常爲JMS編寫)。 http://activemq.apache.org/should-i-use-transactions.html

我不知道這種行爲是與所有的JMS實現一致的,但如果的ActiveMQ您嘗試使用與Session.CLIENT_ACKNOWLEDGEMENT非事務會話,那麼就不會真正表現爲您預期。已經被讀取但未被確認的消息仍然在隊列中,但不會被「釋放」並被傳遞給其他JMS使用者,直到連接斷開到第一個使用者(即connection.close(),崩潰或類似)。

使用本地事務,您可以通過顯式地控制session.commit()和session.rollback()。我沒有看到沒有使用交易的真正意義。確認只是爲了保證交付。

+0

供參考:回滾將增加JMSXDeliveryCount。 JMS隊列配置爲在JMSXDeliveryCount達到閾值後將消息移動到退出隊列。 – Shashi 2012-07-16 03:28:36

+0

在這裏使用交易並不能幫助你,除了確保你從頭到尾加入JTA交易。 – 2012-07-16 17:29:49

+0

當然,但可以配置退貨閾值(取決於供應商)。現在的問題仍然是爲了全面瞭解這個問題。 – 2012-07-16 18:59:59

0

查看此問題的另一種方法是在轉發隊列的情況下。您可以通過執行以下操作將它應用於您的設計:

  1. 在第三方發佈的隊列中創建消費者。
  2. 這位消費者有一份工作 - 將每封郵件分發給其他隊列。
  3. 創建您的真實用戶將收聽的其他隊列。
  4. 將您的消息監聽器編碼爲接收每條消息並將其轉發到各個目標。
  5. 更改每個偵聽器以從其特定隊列中讀取。

通過這樣做,可以確保每一位聆聽者看到的每封郵件,每一筆交易正常工作,而你不知道如何才能發送消息的任何假設(例如,如果發佈方是什麼做AUTO_ACKNOWLEDGE?)

相關問題