无法使用RabbitMQ消息发布选项吗?

时间:2015-08-14 18:00:50

标签: node.js queue rabbitmq

我在我的Node代码中使用ampq.node进行RabbitMQ访问。我尝试使用publishsendToQueue方法使用options参数在我发布的消息(即时间戳和内容类型)中包含一些元数据。

但无论我传递给options的是什么都完全被忽略了。我想我错过了一些格式或字段名称,但我找不到任何可靠的文档(超出提供here的文档似乎没有做到这一点)。

以下是我的publish功能代码:

  var publish = function(queueName, message) {
    let content;
    let options = {
      persistent: true,
      noAck: false,
      timestamp: Date.now(),
      contentEncoding: 'utf-8'
    };
    if(typeof message === 'object') {
      content = new Buffer(JSON.stringify(message));
      options.contentType = 'application/json';
    }
    else if(typeof message === 'string') {
      content = new Buffer(message);
      options.contentType = 'text/plain';
    }
    else {  //message is already a buffer?
      content = message;
    }
    return Channel.sendToQueue(queueName, content, options); //Channel defined and opened elsewhere
  };

我错过了什么?

更新 如果您选择使用ConfirmChannel,则必须将回调函数作为最后一个参数提供,否则将忽略options对象。因此,一旦我将代码更改为以下内容,我就开始正确地看到这些选项:

Channel.sendToQueue(queueName, content, options, (err, result) => {...});

2 个答案:

答案 0 :(得分:2)

不知何故,我似乎无法让你的例子发布工作......虽然我没有看到任何特别错误。我不确定为什么我无法让你的示例代码正常工作。

但是我能够修改我自己的amqplib介绍代码的版本,并且可以正常使用你的选项。

以下是我的示例的完整代码:

// test.js file

var amqplib = require("amqplib");

var server = "amqp://test:password@localhost/test-app";

var connection, channel;

function reportError(err){
  console.log("Error happened!! OH NOES!!!!");
  console.log(err.stack);
  process.exit(1);
}

function createChannel(conn){
  console.log("creating channel");
  connection = conn;
  return connection.createChannel();
}

function sendMessage(ch){
  channel = ch;

  console.log("sending message");
  var msg = process.argv[2];
  var message = new Buffer(msg);

  var options = {
    persistent: true,
    noAck: false,
    timestamp: Date.now(),
    contentEncoding: "utf-8",
    contentType: "text/plain"
  };

  channel.sendToQueue("test.q", message, options);
  return channel.close();
}

console.log("connecting");
amqplib.connect(server)
  .then(createChannel)
  .then(sendMessage)
  .then(process.exit, reportError);

运行它,打开命令行并执行:

node test.js "example text message"

运行之后,您将在“test-app”vhost中看到消息显示在“test.q”队列中(假设您已创建该队列)。

以下是来自RMQ管理插件的结果消息的屏幕截图:

message from rmq server

旁注:

我建议不要使用sendToQueue。正如我在RabbitMQ Patterns email course / ebook中所说的那样:

  

我花了一段时间才意识到这一点,但我现在看到RabbitMQ的“发送到队列”功能是一种反模式。

     

当然,它内置于库和协议中。它很方便,对吗?但这并不意味着你应该使用它。这是使演示简单并处理某些特定场景所存在的功能之一。但一般来说,“发送到队列”是一种反模式。

     

当您是消息生产者时,您只关心使用正确的路由密钥将消息发送到正确的交换机。当您是消息使用者时,您关心消息目标 - 您订阅的队列。可以每天使用相同的路由密钥将消息发送到同一交换机,每天数千次。但是,这并不意味着它每次都会到达同一个队列。

     

当消息使用者联机并脱机时,他们可以创建新的队列和绑定并删除旧的队列和绑定。消息生产者和消费者的这种观点表明了队列的性质:邮箱可以在需要时改变。

我还建议不要直接使用amqplib。这是一个很棒的图书馆,但它缺乏很多可用性。相反,在amqplib上寻找一个好的库。

我更喜欢wascally, by LeanKit。它在amqplib之上更容易抽象,并提供了许多强大的功能和特性。

最后,如果您在使用Node.js获取RMQ并运行其他细节,设计应用程序以使用它等等,请查看我的RabbitMQ For Devs课程 - 它从零到英雄,快。 :)

答案 1 :(得分:0)

这可能会对其他人有所帮助,但是用于内容类型的键名称在JavaScript代码中为 contentType 。通过使用Rabbit Gui的Web Gui,他们使用 content_type 作为键名。不同的键名称来声明选项,因此请确保在正确的上下文中使用正确的键。