我需要限制从rabbitmq队列中消费消息的速度。
我找到了很多建议,但大多数都提供了使用预取选项。但是这个选项不能满足我的需要。即使我将预取设置为1,速率也是大约6000条消息/秒。这对消费者来说太多了。
我需要限制每秒大约70到200条消息。这意味着每5-14ms消耗一条消息。没有同步消息。
我正在使用带有amqp.node库的Node.JS。
答案 0 :(得分:5)
实施令牌桶可能会有所帮助: https://en.wikipedia.org/wiki/Token_bucket
您可以编写一个生产者,以固定的速率向“令牌桶队列”生成消息上的TTL(可能在一秒钟后过期?)或者只设置一个等于每秒速率的最大队列大小。接收“正常队列”消息的消费者还必须接收“令牌桶队列”消息,以便有效地处理消息以限制应用程序。
NodeJS + amqplib示例:
def is_prime(n):
if n<2:
return False # handle special case
sn = int(n**0.5)+1 # +1 because of perfect squares like 49
for i in range(2,sn):
if n%i==0:
return False
return True
答案 1 :(得分:2)
我已经找到了解决方案。
我使用来自npm的module nanotimer来计算延迟。
然后我以纳秒为单位计算delay = 1 / [message_per_second]。
然后我使用prefetch = 1
消费消息然后我计算延迟作为延迟 - [processing_message_time]
然后我在发送消息
之前使超时=真正延迟完美无缺。感谢所有
答案 2 :(得分:1)
参见&#39;公平派遣&#39;在RabbitMQ Documentation。
例如,在有两个工人的情况下,当所有奇怪的消息都很重,甚至消息很轻时,一个工人将经常忙碌而另一个工作人员几乎不会做任何工作。好吧,RabbitMQ对此一无所知,仍然会均匀地发送消息。
这是因为RabbitMQ只是在消息进入队列时调度消息。它没有查看消费者的未确认消息的数量。它只是盲目地向第n个消费者发送每个第n个消息。
为了打败我们可以使用值为1的prefetch方法。这告诉RabbitMQ一次不向一个worker发送一条消息。或者,换句话说,不要向工作人员发送新消息,直到它处理并确认了前一个消息。相反,它会将它发送给下一个仍然不忙的工人。
答案 3 :(得分:0)
我认为RabbitMQ不能为您提供开箱即用的功能。
如果你只有一个消费者,那么整个过程非常简单,只需让它在消费消息之间休息。
如果您有多个消费者,我建议您使用一些“共享内存”来保持费率。例如,您可能有10个消费者使用消息。要在所有消息中保持70-200条消息的速率,您将拨打Redis电话,看看您是否有资格处理消息。如果是,则更新Redis,向其他消费者显示当前正在处理一条消息。
如果您无法控制使用者,请执行选项1或2并将消息发布回Rabbit。这样,原始消费者将以所需的速度消费消息。
答案 4 :(得分:0)
这就是我用 settimeout 修复我的方法
我将我的设置为每 200 毫升处理一次消耗,这将在 1 秒内消耗 5 条数据我做了我的更新(如果存在)
channel.consume(transactionQueueName, async (data) => {
let dataNew = JSON.parse(data.content);
const processedTransaction = await seperateATransaction(dataNew);
// delay ack to avoid duplicate entry !important dont remove the settimeout
setTimeout(function(){
channel.ack(data);
},200);
});
完成