Use of Spring Framework for RabbitMQ is reducing the performance
I have created a producer, which was using com.rabbitmq.client.connectionFactory
and was sending 1,000,000 messages (40 Bytes) in 100 seconds.
But now I want an spring abstraction. I was unable to use com.rabbitmq.client.connectionFactory
rather I had to use org.springframework.amqp.rabbit.connection.SingleConnectionFactory
. Using this connection factory only 100,000 messages (40 Bytes) are send to the broker in 100 seconds.
Does anybody have experience why the performance is reduced so much (around 90%).
The code using "import com.rabbitmq.client.ConnectionFactory;" is ->
package Multiple_queues_multiple_consumers;
import java.io.IOException;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Producer {
private static Connection myConnection;
private static Channel myChannel;
public static String myQueueName;
public static void main(String[] args) throws IOException {
long startTime=0;
int count=0;
ConnectionFactory myFactory=new ConnectionFactory();
myFactory.setHost("localhost");
try {
myConnection = myFactory.newConnection();
myChannel = myConnection.createChannel();
String myExchange = "wxyzabc";
String myBody = "This is a message : message numberxxxxxx";
String myRoutingKey = "RoutingKey";
myQueueName = "new_Queue";
myChannel.exchangeDeclare(myExchange, "direct", true, false, null);
myChannel.queueDeclare(myQueueName, true, false, false, null);
myChannel.queueBind(myQueueName, myExchange, myRoutingKey);
startTime=System.currentTimeMillis();
AMQP.BasicProperties properties = new AMQP.BasicProperties();
properties.setDeliveryMode(2);
startTime=System.currentTimeMillis();
while(count++<=10000){
myChannel.basicPublish(myExchange, myRoutingKey, true, true, properties, myBody.getBytes() );
}
System.out.println(System.currentTimeMillis()-startTime);
} catch (Exception e){
System.exit(0);
}
}
}
The code using SpringFramework is :->
Producer1.java
import org.springframework.amqp.core.AmqpAdmin;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Producer1 {
public static void main(String[] args) {
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("Producer1.xml");
AmqpAdmin amqpAdmin = context.getBean(RabbitAdmin.class);
Queue queue = new Queue("sampleQueue");
DirectExchange exchange = new DirectExchange("myExchange");
Binding binding = new Binding(queue, exchange, "");
amqpAdmin.declareQueue(queue);
amqpAdmin.declareExchange(exchange);
amqpAdmin.declareBinding(binding);
RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);
String routingKey = "";
String myBody = "This is a message : message numberxxxxxx";
Message Msg = new Message(myBody.getBytes(), null);
int count=0;
long CurrTime = System.currentTimeMillis();
while(count++<=10000){
rabbitTemplate.send(routingKey, Msg);
//System.out.println("Message Sent");
}
System.out.println(System.currentTimeMillis()-CurrTime);
}
}
Producer1.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- Define a connectionFactory -->
<bean id="rabbitConnectionFactory" class="com.rabbitmq.client.ConnectionFactory">
<property name="host" value="localhost" />
</bean>
<bean id="connectionFactory" class="org.springframework.amqp.rabbit.connection.SingleConnectionFactory">
<constructor-arg ref="rabbitConnectionFactory"/>
</bean>
<!-- Tell the Admin bean about that connectionFactory and initialize it, c开发者_运维知识库reate a queue and an exchange on Rabbit Broker using the RabbitTemplate provided by Spring framework-Rabbit APIs -->
<bean id="Admin" class="org.springframework.amqp.rabbit.core.RabbitAdmin">
<constructor-arg ref="connectionFactory" />
</bean>
<bean id="rabbitTemplate" class="org.springframework.amqp.rabbit.core.RabbitTemplate"
p:connectionFactory-ref="connectionFactory"
p:routingKey="myRoutingKey"
p:exchange="myExchange" />
</beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<!-- Define a connectionFactory -->
<bean id="connectionFactory" class="com.rabbitmq.client.connectionFactory">
<constructor-arg value="localhost" />
<property name="username" value="guest" />
<property name="password" value="guest" />
</bean>
<bean id="Admin" class="org.springframework.amqp.rabbit.core.RabbitAdmin">
<constructor-arg ref="connectionFactory" />
</bean>
</beans>
Using this xml file, the error appears saying org.springframework.amqp.rabbit.core.RabbitAdmin could not cast com.rabbitmq.client.connectionFactory for connectionfactory bean. The exact error is: "nested exception is java.lang.IllegalStateException: Cannot convert value of type [com.rabbitmq.client.ConnectionFactory] to required type [org.springframework.amqp.rabbit.core.RabbitTemplate]: no matching editors or conversion strategy found" .
Hence i have to use bean:
<bean id="connectionFactory"
class="org.springframework.amqp.rabbit.connection.SingleConnectionFactory">
</bean>
Are you sure that you used the same Rabbit MQ broker? Could you be using a broker on a different server, or an upgraded/downgraded version of RabbitMQ?
The other thing to look at is your jvm. Is it possible that you don't have enough memory configured and now the garbage collector is thrashing? Run top
and see if the jvm's memory usage is close to the configured memory size.
Are you using an old version of RabbitMQ. Lots of Linux distros include RabbitMQ 1.7.2 which is an old version that has problems with large numbers of messages. Large is hard to define because it depends on your RAM, but RabbitMQ does not like to use more than 40% of RAM because it needs to copy a persistence transaction log in order to process it and clean it for log rollover. This can cause RabbitMQ to crash, and, of course, processing the huge logs will slow it down. RabbitMQ 2.4.1 handles the persister logs much better, in smaller chunks, and it also has much, much faster message routing code.
This still sounds to me like a Java problem, either Spring is just a pig and is terribly inefficient, or you have not given your jvm enough RAM to avoid frequent gc runs. What setting are you using for -Xmx?
精彩评论