我有一个场景,在给定的主题上,我需要一个一个地使用每条消息,执行一些异步任务,然后再使用下一条。我正在使用rabbitmq和amqp.node。
我能够以prefetch为1来实现。当然这不是实际的解决方案,因为这会锁定整个频道,并且该频道有多个主题。
到目前为止,这是我的制作人:
const getChannel = require("./getChannel");
async function run() {
const exchangeName = "taskPOC";
const url = "amqp://queue";
const channel = await getChannel({ url, exchangeName });
const topic = "task.init";
let { queue } = await channel.assertQueue(topic, {
durable: true
});
const max = 10;
let current = 0;
const intervalId = setInterval(() => {
current++;
if (current === max) {
clearInterval(intervalId);
return;
}
const payload = JSON.stringify({
foo: "bar",
current
});
channel.sendToQueue(queue, Buffer.from(payload), { persistent: true });
}, 3000);
}
run()
.then(() => {
console.log("Running");
})
.catch(err => {
console.log("error ", err);
});
这是我的消费者
const getChannel = require("./getChannel");
async function run() {
const exchangeName = "taskPOC";
const url = "amqp://queue";
const channel = await getChannel({ url, exchangeName });
channel.prefetch(1);
const topic = "task.init";
const { queue } = await channel.assertQueue(topic, {
durable: true
});
channel.bindQueue(queue, exchangeName, topic);
let last = new Date().getTime();
channel.consume(
queue,
msg => {
const now = new Date().getTime();
console.log(
" [x] %s %s:'%s' ",
msg.fields.routingKey,
Math.floor((now - last) / 1000),
msg.content.toString()
);
last = now;
setTimeout(function() {
channel.ack(msg);
}, 10000);
},
{ exclusive: true, noAck: false }
);
}
run()
.then(() => {
console.log("Running");
})
.catch(err => {
console.log("error ", err);
});
RabbitMQ上有什么方法可以做到这一点,还是需要在我的应用程序上进行处理?
谢谢。
答案 0 :(得分:0)
您可以使用使用者预取设置(请参见https://www.rabbitmq.com/consumer-prefetch.html)。对于amqp节点,您可以使用预取功能设置此选项:
channel.prefetch(1, false); // global=false
在这种情况下,通道上的每个使用者均将预取1。如果您希望为每个使用者具有不同的配置,则应创建更多通道。
希望这会有所帮助。