将ActiveMQ与多个消费者实例一起使用

时间:2018-10-13 19:37:42

标签: java activemq

在我们的体系结构中,每个应用程序都有2个或更多容器,用于 高可用性的puproses。 我们正在使用activeMQ,我想实现以下行为。

  1. 将消息推送到队列。
  2. 此消息仅由*一个*容器(第一个)使用 将会阅读它。)
  3. 消息成功处理后,消费者将对此进行更新 消息可以被确认和忽略
  4. 我尝试使用带有提交的事务和CLIENT_ACKNOWLEDGE,但是 在这两种情况下,两个消费者都收到并处理了消息。

我只希望一个消费者根据可用性来处理每条消息。 我们的实现使用Java。

请分享实现方式。

这是我的代码示例

 final Connection consumerConnection = connectionFactory.createConnection();
    consumerConnection.start();
    // Create a session.
    final Session consumerSession = consumerConnection.createSession(false, Session.CLIENT_ACKNOWLEDGE);

    final Destination consumerDestination = consumerSession.createQueue(queueName);


    // Create a message consumer from the session to the queue.
    final MessageConsumer consumer = consumerSession.createConsumer(consumerDestination);
    // Begin to wait for messages.
    Queue queue = consumerSession.createQueue(queueName);
    QueueBrowser queueBrowser = consumerSession.createBrowser(queue);
    Enumeration msgs = queueBrowser.getEnumeration();
    while (msgs.hasMoreElements()) {
        //do your things here

        ActiveMQTextMessage message = (ActiveMQTextMessage) msgs.nextElement();

        if (message == null)
            continue;

        //handle message
        System.out.println("Message received in : " + message);
        try {
            String text = message.getText();
            JSONObject messageJson = new JSONObject(text);
            consumer.receive(1000);

            String responseString = handleMessage(messageJson);

            message.acknowledge();

谢谢 摩西

1 个答案:

答案 0 :(得分:1)

这里的问题是您正在确认来自QueueBrowser实例的消息,这不会产生任何影响,因为浏览器仅用于浏览消息而不使用消息。

...
QueueBrowser queueBrowser = consumerSession.createBrowser(queue);
Enumeration msgs = queueBrowser.getEnumeration();
while (msgs.hasMoreElements()) {
    ...
    ActiveMQTextMessage message = (ActiveMQTextMessage) msgs.nextElement();
    ...
    try {
        ...
        message.acknowledge(); // this does nothing

实际上是在创建一个真正的消耗并调用consumer.receive(1000),但是您正在丢弃Message返回的receive()实例。这是Message实例,您必须确认该实例才能真正使用队列中的消息。

...
// Create a message consumer from the session to the queue.
final MessageConsumer consumer = consumerSession.createConsumer(consumerDestination);
...
while (msgs.hasMoreElements()) {
    ...
    try {
        ...
        Message actualMessage = consumer.receive(1000); // acknowledge this!
        ...

另一个重要说明...不能保证队列浏览器收到的消息是队列的静态快照。因此,假设您对consumer.receive(1000)的呼叫实际上是来自队列浏览器的相同消息是危险的。我认为您应该重新设计此逻辑,使其仅与MessageConsumer一起使用,并放下QueueBrowser