【问题标题】:Can't publish options with RabbitMQ message?无法使用 RabbitMQ 消息发布选项?
【发布时间】:2015-08-14 18:00:49
【问题描述】:

我在 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,您必须提供回调函数作为最后一个参数,否则,选项对象将被忽略。因此,一旦我将代码更改为以下内容,我就开始正确地看到选项:

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

【问题讨论】:

    标签: node.js queue rabbitmq


    【解决方案1】:

    不知何故,我似乎无法让您的示例发布工作......尽管我看不出它有什么特别的问题。我不确定为什么我无法让您的示例代码正常工作。

    但我能够修改我自己的 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”虚拟主机的“test.q”队列中(假设您已创建该队列)。

    这是 RMQ 管理插件生成的消息的屏幕截图:


    旁注:

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

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

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

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

    随着消息消费者上线和下线,他们可以创建新的队列和绑定并删除旧的队列和绑定。这种消息生产者和消费者的观点体现了队列的本质:可以在需要时更改的邮箱。

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

    我更喜欢wascally, by LeanKit。它是 amqplib 之上的一个更简单的抽象,并提供了许多出色的特性和功能。

    最后,如果您在使用 Node.js 启动和运行 RMQ、设计您的应用程序以使用它等方面遇到其他细节问题,请查看我的 RabbitMQ For Devs 课程 - 它从零到英雄,快速地。 :)

    【讨论】:

    • 感谢德里克的详细回复。我正在使用确认频道这一事实是否会成为问题? (是的,我从示例中删除了回调代码 - 认为它会使它看起来更干净)。
    • 老实说从来没有使用过 ConfirmChannel 插件,所以我不知道这是否会导致这样的事情。我不这么认为……但我不知道。
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-24
      • 1970-01-01
      • 2016-08-23
      • 1970-01-01
      • 1970-01-01
      • 2012-03-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多