Reputation: 1505
I am creating a REST api to send message to RabbitMQ and was trying to understand what are the best practice for creating/closing channels. I am using RabbitMQ Java client api.
Currently I have a class RabbitMQPublisherConnection
where I spring inject RabbitMQ connection. This class is then spring injected to another class RabbitMQPublisherChannel
. This class has the following function to create a channel:
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; } }
Now I have the third class RabbitMQPublisher
where I spring inject RabbitMQPublisherChannel
class. My application context looks like this:
<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>
The class RabbitMQPublisher
has the function to publish a message to 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;
}
This application is run through tomcat and I noticed with AppDynamics that the closing the channel takes like 47% of the total time taken to publish message. When I remove the call to close the channel then I save this 47% of time which is like 32ms but then I notice in my RabbitMQ management console that the number of channel is ever increasing for that connection.
So my questions are -
Even so, applications should prefer using a Channel per thread instead of sharing the same Channel across multiple threads.
) Does this mean create a new channel for every thread?Thanks
Upvotes: 2
Views: 4498
Reputation: 174554
Since you are a Spring Framework user, consider using Spring AMQP. The RabbitTemplate
uses cached channels over a single connection with the channel being checked out of the cache (and returned) for each operation. The default cache size is 1, so it generally needs to be configured for an environment like yours.
Upvotes: 3