.net core RabbitMQ使用者在存在未确认的消息时变慢

.net core RabbitMQ使用者在存在未确认的消息时变慢,.net-core,rabbitmq,.net Core,Rabbitmq,我有一个.NET核心控制台应用程序,它从RabbitMQ读取消息并将数据保存到数据库。它使用RabbitMQ.Client assembly 5.1.0并设置如下EventingConsumer: var factory = new ConnectionFactory { HostName = _hostName, UserName = _userName, Password = _password, RequestedHeartbeat = 20, Au

我有一个.NET核心控制台应用程序,它从RabbitMQ读取消息并将数据保存到数据库。它使用RabbitMQ.Client assembly 5.1.0并设置如下EventingConsumer:

var factory = new ConnectionFactory
{
    HostName = _hostName,
    UserName = _userName,
    Password = _password,
    RequestedHeartbeat = 20,
    AutomaticRecoveryEnabled = true,
    NetworkRecoveryInterval = TimeSpan.FromSeconds(10)
};

_connection = factory.CreateConnection();
_channel = _connection.CreateModel();
_channel.BasicQos(0, prefetchCount, false);

var consumer = new EventingBasicConsumer(_channel);
consumer.Received += HandleMessage;
_consumerTag = _channel.BasicConsume(_queueName, false, consumer);
如果我在我的
HandleMessage
方法中对消息调用
\u channel.BasicAck
,即,一旦收到每条消息,发送消息的速率约为1500/秒。但是,我想等待确认消息,直到它保存到数据库。如果我这样做,速率会下降到300-500/秒

保存到数据库是在单独的线程上完成的,不是瓶颈
HandleMessage
仅将消息存储在内存中,以便稍后在另一个线程上保存。我尝试过使用从100到100000的各种
prefetchCount
值进行实验,但这似乎并不重要。如果我分析应用程序,我可以看到AMQP会话线程(“工作池会话#1:Connection(…)”将其大部分时间花费在
RabbitMQ.Client.ConsumerWorkService+WorkPool.Loop()中的等待句柄上。


我做错了什么?如何在不立即确认消息的情况下更快地使用消息?(服务器是RabbitMQ 3.7.7)

预回迁计数限制将发送给消费者的未确认邮件的数量。您可以增加此值,以便在不确认的情况下从队列接收更多邮件

但是,由于数据库持久性似乎是瓶颈,我希望交付率保持不变: 假设每条消息需要2毫秒才能完成数据库插入,即500次插入/秒。一旦您将未完成消息的数量(预回迁计数)设置为最大值,您将以500条消息/秒的速率进行确认,因此您将以该速率获得新消息。缓冲区大小对瓶颈影响不大


为了提高系统吞吐量,您可以增加额外的使用者,或者以某种方式(即大容量插入、模式改进、分片)提高数据库的吞吐量,但RabbitMQ无法保持无限多的未确认(正在进行中)的吞吐量消息。

数据库持久性不是瓶颈。它已经批量完成,当MQ读卡器读取速度足够快时,可以在~0.2-0.3毫秒/消息内完成。在任何情况下,它都是在单独的线程上完成的,我可以设置非常高的完整性限制(如100K)这在很长一段时间内都没有受到影响,但消息传递的速度仍然变慢。本质上,这是我试图理解的奇怪行为:如果不确认消息,即使没有达到预取限制,传递的速度也会低很多。我甚至尝试用一个简单的线程替换保存到DB的代码。睡眠()有不同的值,但对RabbitMQ传递速率没有影响。速率也不是恒定的:有时跳到1800/秒,有时降到150/秒。@EM0您在这个问题上有过任何进展吗?@MNilson No.顺便说一句,我遇到过消息读取速率是瓶颈的情况,比如M.a。哈宁在这里说,但我认为这并不能解释预取限制还没有达到的情况,但是没有自动确认的情况下获取要比使用自动确认的情况慢得多。