JMS-一个队列和多个接收器(使用者)
我有一个由第三方发布的JMS队列。 我想在不同的机器上设置多个消费者,只有一个特定机器的消费者,确认该队列上的消息。简言之,如果特定计算机的使用者未收到该消息,则不应从队列中删除该消息。JMS-一个队列和多个接收器(使用者),jms,consumer,Jms,Consumer,我有一个由第三方发布的JMS队列。 我想在不同的机器上设置多个消费者,只有一个特定机器的消费者,确认该队列上的消息。简言之,如果特定计算机的使用者未收到该消息,则不应从队列中删除该消息。 这是可以实现的吗 好的,您可能有自己的理由进行此设置,而且很容易实现 我将使用本地会话事务。根据某些标准(例如哪个服务器正在使用消息)提交或回滚事务相当容易。如果回滚,消息将再次在队列中首先结束 示例代码可能如下所示: public class MyConsumer implements MessageList
这是可以实现的吗 好的,您可能有自己的理由进行此设置,而且很容易实现 我将使用本地会话事务。根据某些标准(例如哪个服务器正在使用消息)提交或回滚事务相当容易。如果回滚,消息将再次在队列中首先结束 示例代码可能如下所示:
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在JavaEE容器中执行此操作,并且您使用的是UserTransactions,那么您可以调用UserTransaction.setRollBack();
或者,如果您使用的是声明性事务,您可以在读取消息并完成操作后,抛出运行时异常以使事务失败并将消息回滚到队列中。注意,这种方法也会回滚数据库更改(如果您使用的是JTA而不是本地JMS事务)
更新:
您确实应该使用事务来完成这项工作,而不是使用确认
这里可以找到本主题的摘要(针对ActiveMQ,但通常是为JMS编写的)。
我不知道这种行为是否与所有JMS实现一致,但对于ActiveMQ,如果您尝试使用带有session.CLIENT_确认的非事务会话,那么它将不会真正像您所期望的那样工作。已读取但未确认的消息仍在队列中,但在与第一个使用者的连接断开(即connection.close()、崩溃或类似情况)之前,不会被“释放”并传递给其他JMS使用者
通过使用本地事务,您可以显式地通过session.commit()和session.rollback()控制此操作。我认为不使用事务没有任何实际意义。确认只是为了保证交付。另一种方法是在转发队列的情况下。您可以通过执行以下操作将其应用于您的设计:
通过这样做,您可以确保每个侦听器都能看到每一条消息,每一个事务都按预期工作,并且您不会对消息的发送方式做出任何假设(例如,如果发布方正在执行
自动确认
?)不知道是什么原因,我认为所有消费者都必须收到一条消息,但只有一个特定的消费者会确认该消息。如果不是这样,为什么您希望同一队列有多个使用者?仅供参考:回滚将增加JMSXDeliveryCount。JMS队列配置为在JMSXDeliveryCount达到阈值后将消息移动到回退队列。在此处使用事务对您没有任何帮助,只能确保您从端到端加入JTA事务。当然,但可能可以配置回退阈值(取决于供应商)。当然,如果您回滚事务并且没有回退队列接收消息,那么其他消费者将可以使用它。当然,最好对消息进行适当的路由,但我在这里看不到完整的情况。