【问题标题】:ActiveMQ consumer level timeoutActiveMQ 消费者级别超时
【发布时间】:2019-03-08 04:53:33
【问题描述】:

我尝试在 Active MQ(版本 5.15.0)中创建消费者级别超时。考虑一条消息被消费者选择但无法确认,所以在这种情况下,我希望消费者超时,以便其他消费者可以选择相同的消息来监听代理。

我设置两个消费者监听器的生产者代码:

public class JmsMessageListenerAckExample {
  public static void main(String[] args) throws URISyntaxException, Exception {
    Connection connection = null;
    try {
      // Producer
      ConnectionFactory factory = createActiveMQConnectionFactory();
      connection = factory.createConnection();
      Session session = connection.createSession(false,
          Session.CLIENT_ACKNOWLEDGE);
      Queue queue = session.createQueue("customerQueue");
      String payload = "Important Task";
      Message msg = session.createTextMessage(payload);
      MessageProducer producer = session.createProducer(queue);

      System.out.println("Sending text '" + payload + "'");
      producer.send(msg);

      // Consumer
      MessageConsumer consumer1 = session.createConsumer(queue);
      consumer1.setMessageListener(
          new AckMessageListener(false, "consumer1"));
      Thread.sleep(1000);
      System.out.println("Creating new message listener to acknowledge");
      producer.send(msg);
      MessageConsumer consumer2 = session.createConsumer(queue);
      consumer2.setMessageListener(
          new AckMessageListener(true, "consumer2"));
      connection.start();

      Thread.sleep(3000);
      session.close();
    } finally {
      if (connection != null) {
        connection.close();
      }
    }
  }

  private static ActiveMQConnectionFactory createActiveMQConnectionFactory() {
    // Create a connection factory.
    final ActiveMQConnectionFactory connectionFactory =
        new ActiveMQConnectionFactory("tcp://localhost:61616");

    // Pass the username and password.
    connectionFactory.setUserName("user");
    connectionFactory.setPassword("user");
    return connectionFactory;
  }
}

这是我的消费者监听器:

public class AckMessageListener implements MessageListener {
  private boolean acknowledge;
  private String consumerName;

  public AckMessageListener(boolean acknowledge, String consumerName) {
    this.acknowledge = acknowledge;
    this.consumerName = consumerName;
  }

  public void onMessage(Message message) {
    boolean terminate = !acknowledge;
    try {

      System.out.println("ConsumerName="+consumerName+", Acknowledge="+acknowledge);
      if (acknowledge) {
        try {
          message.acknowledge();
        } catch (JMSException e1) {
          e1.printStackTrace();
        }
      }

      System.out.println(message);
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      if (terminate) {
        Thread.currentThread().interrupt();
      }
    }
  }
}

我想以consumer1 收听消息但不确认的方式进行模拟,以使其超时以便消息在代理中从“消息入队”状态移动到“消息出队”状态,但我的 consumer2 无法接收任何消息事件。

我做错了什么吗。如何使用 Active MQ 实现消费者级别的超时?

【问题讨论】:

标签: java jms activemq producer-consumer


【解决方案1】:

处理此问题的一种方法是使用事务 (http://activemq.apache.org/how-do-transactions-work.html)。您在成功时调用 commit(),在失败时调用 rollback(),或者如果会话在调用 commit() 之前关闭,则将发生重新传递 (http://activemq.apache.org/message-redelivery-and-dlq-handling.html)。

【讨论】:

  • 即使有事务会话并进行回滚,仍然是同一个消费者在挑选消息。我还需要设置其他配置吗?
  • 好吧,我误解了这个问题。我认为您想保留该消息,以防您的消费者 1 在处理消息时死亡,然后您希望消费者 2 接收该消息。但似乎您想从一个消费者回滚并希望第二个消费者接收消息。我不知道是否有这样做的 ActiveMQ(整洁)方式。 ActiveMQ 正在重新尝试交付(以循环方式)。我不确定您的最终目标是什么,但是向两个消费者发送相同消息的副本是否对您有用?如果是,您可以为此使用复合目的地。
猜你喜欢
  • 2019-10-03
  • 2014-08-06
  • 2016-06-08
  • 2012-04-18
  • 2021-12-02
  • 2012-12-24
  • 1970-01-01
  • 2019-10-27
  • 2021-03-06
相关资源
最近更新 更多