使用RabbitMQ可以放慢同步发布/消耗速度

时间:2013-12-11 10:20:21

标签: rabbitmq amqp

我正在评估RabbitMQ,虽然(AMQP本身,以及RabbitMQ)的总体印象是积极的,但结果并没有让我印象深刻。

我正在尝试同时发布和使用消息,并且已经实现了非常差的消息速率。我有一个持久的直接交换,它绑定到一个持久的队列,我向该交换发布持久性消息。邮件正文的平均大小约为1000字节。

我的发布大致如下:

AMQP.BasicProperties.Builder bldr = new AMQP.BasicProperties.Builder();
ConnectionFactory factory = new ConnectionFactory();
factory.setUsername("guest");
factory.setPassword("guest");
factory.setVirtualHost("/");
factory.setHost("my-host");
factory.setPort(5672);
Connection conn = null;
Channel channel = null;
ObjectMapper mapper = new ObjectMapper(); //com.fasterxml.jackson.databind.ObjectMapper
try {
    conn = factory.newConnection();
channel = conn.createChannel();
    channel.confirmSelect();
} catch (IOException e) {}

for(Message m : messageList) { //the size of messageList happens to be 9945
    try {
        channel.basicPublish("exchange", "", bldr.deliveryMode(2).contentType("application/json").build(), mapper.writeValueAsBytes(cm));
    } catch (Exception e) {}
}
try {
    channel.waitForConfirms();
    channel.close();
conn.close();
} catch (Exception e1) {}               

使用来自绑定队列的消息如下:

AMQP.BasicProperties.Builder bldr = new AMQP.BasicProperties.Builder();
ConnectionFactory factory = new ConnectionFactory();
factory.setUsername("guest");
factory.setPassword("guest");
factory.setVirtualHost("/");
factory.setHost("my-host");
factory.setPort(5672);
Connection conn = null;
Channel channel = null;
try {
    conn = factory.newConnection();
    channel = conn.createChannel();
    channel.basicQos(100);
    while (true) {
        GetResponse r = channel.basicGet("rawDataQueue", false);
        if(r!=null)
            channel.basicAck(r.getEnvelope().getDeliveryTag(), false);
    }
} catch (IOException e) {}

问题在于,当消息发布者(或其中几个)和消费者(或其中几个)同时运行时,发布者似乎全速运行,而RabbitMQ管理Web界面显示的发布率为比方说,每秒约2 ... 3K消息,但每个消费者的消费率为0.5 ... 3。当出版商完成后,我得到的消费率为每个消费者300到600条消息。如果没有为Java客户端设置QOS预取值,那么在将其设置为100或250时会少一点,然后再多一点。

在尝试对某些消费者进行限制时,我已经设法实现了同时发布的数据,例如每周发布约400条消息,每秒消耗约50条消息,这些消息略微好一些,但只是略有下降。

Here's,这是来自RabbitMQ博客条目的引用,该条目声称队列在空闲状态时最快,但是当有几千条持续消息存在时,消耗速度会降低到爬行速度在队列中仍然是相当不可接受的。

较高的QOS预取值可能会有所帮助,但恕我直言不是这样的解决方案。

如果有的话,可以做些什么来达到合理的吞吐率(每个消费者每秒消耗2条消息在任何情况下都不合理)?这只是一个简单的直接交换 - 一个绑定 - 一个队列情况,我应该期望更复杂的配置会导致性能下降吗?在互联网上搜索时,也有建议放弃耐久性,但我担心在我的情况下这不是一个选择。如果有人会指出我是愚蠢的并且某种明显而直接的解决方案,我会很高兴:)

2 个答案:

答案 0 :(得分:5)

您是否尝试过autoAck选项?这应该可以改善你的表现。它比逐个获取消息并快速获取消息要快得多。增加预取计数也应该会更好。

此外,您发送和使用的邮件大小包括标题?您是否在经纪人中遇到任何流量控制?

另一个问题是,您每次发送/收到消息时都在创建连接和频道吗?如果是这样,那就错了。您应该创建一次连接,并使用每个线程的通道(可能以线程本地方式)来发送和接收消息。每个连接可以有多个通道。没有关于此的官方文档,但如果您阅读文章和论坛,这似乎是最佳表现实践。

最后,您是否考虑过使用basicConsume代替basicGet?它也应该使它更快。

根据我的经验,我能够使用非持久性消息以每秒约20000条消息的速率运行群集。我想如果你使用持久和持久的消息,性能会略微降低,但不会降低10倍。

答案 1 :(得分:-1)

如果使用sleep,操作系统可以将您的流程安排到下一个时间段。这可能会导致性能显着下降。