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

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

В настоящее время у меня есть класс 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 мс?

Спасибо

1 ответ

Решение

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

Другие вопросы по тегам