2012-07-15 113 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?)

相关问题