我有一个将消息排队到RabbitMQ的功能,如下所示:
var amqp = require('amqplib/callback_api');
var _queueURL = 'amqp://127.0.0.1';
var _toBlahBlahQueueName = 'blahblah';
var self = module.exports = {
queueMessage: function (msgObj, callback) {
try {
amqp.connect(_queueURL, function (err, connection) {
if (err) {
callback(err);
}
connection.createChannel(function (err, channel) {
if (err) {
callback(err);
}
channel.assertQueue(_toBlahBlahQueueName, { durable: true }, function (err, _ok) {
if (err) {
callback(err);
}
var msg = new Buffer(JSON.stringify(msgObj));
channel.sendToQueue(_toBlahBlahQueueName, msg, { persistent: true }, function (err, ok) {
if (err) {
console.log(err);
callback(err);
}
console.log('published', ok);
channel.connection.close();
callback(null, { message: 'queued' });
});
});
});
});
}
catch (e) {
console.log(e.stack);
callback(e);
}
}
};
我正在调用函数queueMessage,其中包含大约250K的消息。
sendToQueue调用每次都挂起。它只是坐在那里而不会返回错误。但是,该消息似乎排队了!
服务器日志有错误消息:客户端意外关闭TCP连接
感谢您的帮助!
答案 0 :(得分:4)
amqplib不支持sendToQueue
或publish
的回调。
the documentation表明这不是一个选项:
通道#sendToQueue 承诺和回调
sendToQueue(队列,内容,[选项])
发送一条消息,其中包含作为缓冲区的内容 队列命名,绕过路由。选项和返回值完全相同 与发布相同。
要解决此问题,您需要将sendToQueue
称为同步消息。
如果您想立即退出应用程序,则必须等待几毫秒才能执行此操作。如果不这样做,将导致邮件无法发送。
以下是如何将代码更改为以这种方式工作的示例:
channel.sendToQueue(_toBlahBlahQueueName, msg, { persistent: true });
setTimeout(function () {
channel.connection.close();
callback(null, { message: 'queued' });
}, 500);
答案 1 :(得分:0)
如果您需要对回调的支持或承诺,则另一个解决方案可能是使用“ ConfirmChannel” RabbitMQ扩展。
> RabbitMQ ConfirmChannel docs
我的问题是,即使ch.sendToQueue()
返回了true
,在消息实际完成发送之前,Node.js进程仍在退出。
我的解决方案是将conn.createChannel()
更改为conn.createConfirmChannel()
,这使我可以await ch.sendToQueue()
。这可能对您有用,但请记住,这会产生额外的开销。