我有一个使用RabbitMQ的项目。在最好的情况下,它每秒可以接收3000条消息。这是我的消费者代码:
package com.mdnaRabbit.worker;
import java.io.IOException;
import java.math.RoundingMode;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.QueueingConsumer;
import com.mdnaRabbit.worker.data.Data;
import org.apache.commons.lang.SerializationUtils;
public class App {
private static final String TASK_QUEUE_NAME = "task_queue";
private static int i = 0;
private static long timeStart;
private static long timeFinish;
private static long messPerSec;
public static void main (String[] argv) throws IOException,InterruptedException{
ExecutorService threader = Executors.newFixedThreadPool(20);
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection(threader);
final Channel channel = connection.createChannel();
channel.queueDeclare(TASK_QUEUE_NAME, true, false, false, null);
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
channel.basicQos(50);
final QueueingConsumer consumer = new QueueingConsumer(channel);
channel.basicConsume(TASK_QUEUE_NAME, false, consumer);
timeStart = System.currentTimeMillis();
try {
while (i<100000) {
try {QueueingConsumer.Delivery delivery = consumer.nextDelivery();
Data mess = Data.fromBytes(delivery.getBody());
System.out.println(" [" + (i++) +"] Received " + mess.getHeader());
channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
}catch (Exception e){
}
}
} catch (Exception e){
e.printStackTrace();
}
timeFinish = System.currentTimeMillis();
messPerSec = Math.round ((i*1000)/(timeFinish - timeStart));
System.out.println( "receives " + messPerSec + " per second");
channel.close();
connection.close();
}
}
如您所见,我正在使用ExecutorService来提高速度和channel.basicQos(),但它对我没什么帮助。有没有办法提高接收/发送速度(发送速度增加,我认为与接收速度相同)
答案 0 :(得分:4)
我之前没有使用过RabbitMQ,但我可以从其他消息传递中间件中分享我的经验。毕竟他们面临着同样的挑战。
通过调整MQ服务器,您可以增加每秒的消息数量,但是您必须放弃某种功能,例如:保证交货。如果使用单个队列,则添加的线程越多,队列锁定的争用就越多。
我过去所做的并且设法将性能提高到x300倍是为了增加消息大小,即增加单个线程可以原子方式完成的工作。我将尝试在下面描述我的算法(如果有人知道它的名字,我将不胜感激。)
threadLocal
集合(4)。您不仅可以消除网络延迟,还可以消除磁盘IO时间,因为正常的HDD将需要相同的时间来写入1字节和大约1.5MB。
*
在我的情况下,这更复杂,因为每个交付线程都应该得到保证。为了支持这一点,您需要实现某种Barrier
,以便传递线程将阻塞,直到主线程收到ACK
**
您可能还希望在一条消息失败时实施备份策略,这意味着整个批处理将失败。如果批次失败,我建议发送单独的消息。
***
在其他MQ中,有各种设置可能会阻止您的性能。这些包括限制,限制生产者超过一定大小的队列,批处理消费者消息,多级保证模式。 (见下面的潜在组合)
****
可能会降低性能的组合如下:队列的最大大小为10MB,消费者预先获取1000个消息。为了举例,我们假设每条消息的大小都是10K。此示例将导致(在某些MQ中)单个使用者线程获取所有消息(即使您有100个使用者线程)。另一方面,生产者将被限制,不允许添加超过10MB限制的任何消息。这里的解决方案是增加队列MaxSize并减少预取大小。监控/分析/记录始终是您的朋友。
希望这可以更好地理解您的问题。 (顺便说一句,持续模式下的3000msgs /秒也不错。)