Чтение из нескольких обменов RabbitMQ в клиенте Java не опрос

1

Объясните, как настроить клиент Java для чтения из двух разных обменов RabbitMQ без опроса. Я хотел бы, чтобы клиент пробудился, когда приходит сообщение, а затем снова заблокируется.

В моей маленькой проблеме системной интеграции один обмен RabbitMQ несет рабочие сообщения с использованием различных ключей маршрутизации (я знаю, как использовать подстановочные знаки, чтобы их поймать), а другой обмен несет управляющие сообщения (например, "стоп"). Поэтому мой клиент должен слушать сообщения из обоих мест. Это относительно низкая системная проблема, я не спрашиваю о распределении нагрузки или справедливости и т.д.

Конечно, я мог бы запустить поток, который опросит каждый обмен, спит, отправляет, навсегда. Но я бы хотел избежать опроса.

Мне как-то напоминает системный вызов Unix select(), который пробуждается, когда данные готовы к любому из дескрипторов файлов, переданных ему. Есть ли у RabbitMQ что-то подобное?

Мое текущее решение - это адаптер, который объединяет поток для блокировки при каждом обмене вводами; после получения каждый поток записывает в коллекцию java.util.concurrent; и я использую еще один поток для блокировки этой коллекции и доставки сообщений по мере их поступления в конечного потребителя. Он отлично работает, но если я смогу избавиться от этой сложности, это будет здорово.

Эти SO-сообщения танцуют вокруг проблемы, пожалуйста, не стесняйтесь втирать нос в решение, если я упустил это в этих сообщениях:

Для java: RabbitMQ по примеру: несколько потоков, каналов и очередей

Для С#: чтение из нескольких очередей, RabbitMQ

Заранее спасибо.

Теги:
rabbitmq

1 ответ

1
Лучший ответ

Спасибо, robthewolf, за комментарий. Да, я прочитал учебники, и я знаю, что мне нужен поток для каждого потребителя.

Оказывается, это просто читать с нескольких обменов с одним потоком и вообще не проводить опрос: получить новую очередь и привязать ее ко всем соответствующим обменам. Работает для темы и разветвления. Протестировано с помощью SSCE, см. Ниже.

Я жалуюсь на отсутствие деталей в javadoc RabbitMQ, несколько слов выбора в методе Channel # queueBind (String, String, String) помогли бы многим.

НТН

package rabbitExample;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;

/**
 * Demonstrates reading messages from two exchanges via a single queue monitored
 * by a single thread.
 * 
 */
public class MultiExchangeReadTest implements Runnable {

private final String exch1 = "my.topic.exchange";
private final String exch2 = "my.fanout.exchange";
private final Channel channel;
private final QueueingConsumer consumer;

public MultiExchangeReadTest(final String mqHost) throws Exception {

    // Connect to server
    System.out.println("Connecting to host " + mqHost);
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost(mqHost);
    Connection connection = factory.newConnection();
    channel = connection.createChannel();

    // Declare exchanges; use defaults for durable etc.
    channel.exchangeDeclare(exch1, "topic");
    channel.exchangeDeclare(exch2, "fanout");

    // Get a new, unique queue name
    final String queue = channel.queueDeclare().getQueue();

    // Bind the queue to the exchanges; topic gets non-empty routing key
    channel.queueBind(queue, exch1, "my.key");
    channel.queueBind(queue, exch2, "");

    // Configure the channel to fetch one message at a time, auto-ACK
    channel.basicQos(1);
    consumer = new QueueingConsumer(channel);
    channel.basicConsume(queue, true, consumer);
}

public void run() {
    // Reads messages until interrupted
    try {
        while (true) {
            // Wait for a message
            System.out.println("Awaiting message");
            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
            // Show contents using default encoding scheme
            String body = new String(delivery.getBody());
            System.out.println("Message from exch "
                    + delivery.getEnvelope().getExchange() + ", key '"
                    + delivery.getEnvelope().getRoutingKey() + "':\n"
                    + body);
        } // while
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

public static void main(String[] args) throws Exception {
    if (args.length != 1) {
        System.err
                .println("Usaage: MultiExchangeReadTest.main mq-host-name");
    } else {
        MultiExchangeReadTest multiReader = new MultiExchangeReadTest(
                args[0]);
        multiReader.run();
    }
}
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню