Лучшие практики канала RabbitMQ

Я создаю API REST для отправки сообщения RabbitMQ и пытаюсь понять, как лучше всего создавать/закрывать каналы. Я использую клиентский API RabbitMQ Java.

В настоящее время у меня есть класс RabbitMQPublisherConnection, где я подключаю соединение RabbitMQ. Затем этот класс вводится в другой класс RabbitMQPublisherChannel. Этот класс имеет следующую функцию для создания канала:

public class RabbitMQPublisherChannel {

public Channel createChannel(String amqpExchange,
                                         String exchangeType,
                                         String queue,
                                         String routingKey,
                                         boolean durableExchange,
                                         boolean durableQueue,
                                         boolean autoDelete,
                                         com.rabbitmq.client.Connection connection) throws IOException {
        Channel channel = null;
        channel = connection.createChannel();

        if ((amqpExchange != null) && !"".equals(amqpExchange.trim())) {
            if (log.isLoggable(Level.FINEST)) {
                log.finest("exchange:" + amqpExchange + ", type: " + exchangeType + ", durableExchange: " + durableExchange);
            }
            channel.exchangeDeclare(amqpExchange, exchangeType, durableExchange);
            channel.queueDeclare(queue, durableQueue, false, autoDelete, null);
            channel.queueBind(queue, amqpExchange, routingKey);
        }
        return channel;
    } }

Теперь у меня есть третий класс RabbitMQPublisher, в который я вставляю класс RabbitMQPublisherChannel. Контекст моего приложения выглядит так:

<bean id="rabbitMQPublisher" class="com.rabbitmq.RabbitMQPublisher">
    <property name="publisherChannel"     ref="rabbitMQPublisherChannel"/>
</bean>

<bean id="rabbitMQPublisherChannel" class="com.rabbitmq.RabbitMQPublisherChannel">
    <property name="publisherConnection"     ref="rabbitMQPublisherConnection"/>
</bean>

<bean id="rabbitMQPublisherConnection" class="com.rabbitmq.RabbitMQPublisherConnection">
    <property name="rabbitMQConnectionSettingMap">
        .. connection ..
    </property>
</bean>

Класс RabbitMQPublisher имеет функцию публикации сообщения в RabbitMQ:

public boolean publishMessage(String message, String queueName){

    try {
        // Validate queue name
        com.rabbitmq.client.Channel channel     = publisherChannel.getRabbitMQChannel(queueName);
        RabbitMQConnection          settings    = publisherChannel.getPublisherConnection().getRabbitMQConnectionSettingMap().get(queueName);

        if (channel != null) {
            channel.basicPublish(settings.getAmqpExchange(), settings.getAmqpRoutingKey(), null, message.getBytes());
            publisherChannel.closeChannel(channel);
        }
    } catch (AlreadyClosedException e) {
        return FAILURE_RESPONSE;
    } catch (IOException e) {
        return FAILURE_RESPONSE;
    }
    return SUCCESS_RESPONSE;
}

Это приложение запускается через tomcat, и я заметил с помощью AppDynamics, что закрытие канала занимает около 47% от общего времени, затрачиваемого на публикацию сообщения. Когда я удаляю вызов, чтобы закрыть канал, я сохраняю эти 47% времени, что составляет около 32 мс, но затем я замечаю в своей консоли управления RabbitMQ, что количество каналов для этого соединения постоянно увеличивается.

Итак, мои вопросы -

  1. Является ли хорошей практикой открывать и закрывать канал после каждой публикации, предполагая, что tomcat будет получать несколько запросов в секунду?
  2. Является ли хорошей практикой совместное использование пула каналов несколькими потоками (что RabbitMQ рекомендует но также говорит Even so, applications should prefer using a Channel per thread instead of sharing the same Channel across multiple threads.) Означает ли это создание нового канала для каждого потока?
  3. Будет ли хорошей практикой не закрывать канал и через каналы очистки RabbitMQ http api, которые простаивают. (Пожалуйста, не рекомендуйте это)?
  4. Стоит ли экономить 32 мс?

Спасибо


person Sumitk    schedule 13.03.2015    source источник


Ответы (1)


Поскольку вы являетесь пользователем Spring Framework, рассмотрите возможность использования Spring AMQP. RabbitTemplate использует кэшированные каналы по одному соединению, при этом канал извлекается из кэша (и возвращается) для каждой операции. Размер кэша по умолчанию равен 1, поэтому обычно его необходимо настроить для такой среды, как ваша.

person Gary Russell    schedule 13.03.2015
comment
Спасибо @Gary! Я использовал spring-amqp, и им было очень легко пользоваться. Он также очень хорошо структурирован. У меня всего несколько вопросов: насколько велико сообщество, использующее или вносящее свой вклад в это? И сколько людей уже используют его в производстве? Я очень новичок в этом, поэтому волновался, получу ли я достаточно помощи, если я выйду в эфир и возникнет проблема, которую я не могу понять. - person Sumitk; 16.03.2015
comment
Спасибо за информацию Гэри! Да, spring-amqp выглядит очень аккуратно, и я подумываю использовать его сейчас. У вас есть какой-нибудь IRC, где я могу задать несколько простых вопросов, или Stackoverflow — единственный лучший способ для этого? Также есть ли какие-либо рекомендации по развертыванию производства? Спасибо - person Sumitk; 16.03.2015
comment
StackOverflow — это форум вопросов для Spring AMQP; используйте тег [spring-amqp] (но мы также отслеживаем весенний кролик). Spring AMQP — это просто библиотека Java, поэтому развертывать нечего. Вам нужно посмотреть документацию rabbitmq для характеристик конфигурации/развертывания брокера. Конкретные вопросы по rabbitmq см. в группе rabbitmq-users google (но не задавайте там конкретные вопросы по Spring-AMQP). - person Gary Russell; 16.03.2015