使用amqp.node异步发送和监听

时间:2015-04-01 21:11:19

标签: amqp

我试图理解为什么在使用amqp.node(https://github.com/squaremo/amqp.node)时,似乎我在出列或处理这些消息之前将所有消息排队。我希望发送和接收是交错的。

发送 - 接收 - 发送 - 接收

但是我得到了

发送-发送 - 接收 - 接收

在检查我的进程时,我发现在进入任何接收之前,我将首先完成所有发送。我已经写了一个简单的演示,说明我遇到的问题

var amqp = require('amqplib');
var prettyHrtime = require('pretty-hrtime');
var when = require('when');

var firstMesssage = false;
var time, diff, totaltime;
var received = 0;

amqp.connect('amqp://localhost', { noDelay: false } ).then(function(conn) {
  process.once('SIGINT', function() { conn.close(); });
  return conn.createChannel().then(function(ch) {

    var ok = ch.assertQueue('hello', {durable: false});

    ok = ok.then(function(_qok) {
      return ch.consume('hello', function(msg) {

        if(!firstMesssage){
          time = process.hrtime();
          firstMesssage = true;
        }

        received++;
        console.log(new Date().getTime());
        console.log(" [x] Received '%s' %s", msg.content.toString(), received);
        if(received >= 10000){
          diff = process.hrtime(time);
          var words = prettyHrtime(diff);
          console.log(words);
        }
      }, {noAck: true});
    });

    return ok.then(function(_consumeOk) {
      console.log(' [*] Waiting for messages. To exit press CTRL+C');
    });
  });
}).then(null, console.warn);



var numberToSend = 10000;
var numberDone = 0;

amqp.connect('amqp://localhost', { noDelay: false } ).then(function(conn) {
  return when(conn.createChannel().then(function(ch) {
    var q = 'hello';
    var msg = 'Hello World!';

    var ok = ch.assertQueue(q, {durable: false});

    function sendMsg(){
      ch.sendToQueue(q, new Buffer(msg));
      console.log(" [x] Sent '%s'", msg, new Date().getTime());
      numberDone++;
    }

    return ok.then(function(_qok) {
      while(numberDone < numberToSend){
        sendMsg();
      }
      console.log('*** done');
      return ch.close();

    });
  })).ensure(function() { conn.close(); });
}).then(null, console.warn);

1 个答案:

答案 0 :(得分:1)

节点是单线程的,因此无法处理任何传入的消息,直到完成所有发送的while循环完成。

尝试将sendMsg包裹在setImmediate电话中,看看它如何改变(它必须转换为承诺并链接,以便频道和连接不会在一切都发送之前关闭)

function sendMsg(resolve){
  setImmediate(function() {
    ch.sendToQueue(q, new Buffer(msg));
    console.log(" [x] Sent '%s'", msg, new Date().getTime());
    resolve();
  });
}

return ok.then(function(_qok) {
  var sendOk = when.promise(sendMsg);
  while(numberDone < numberToSend){
    sendOk = sendOk.then(function() {
      return when.promise(sendMsg);
    });
    numberDone++;
  }

  return sendOk.finally(function() {
    console.log('*** done');
    ch.close(); 
  });
});

即使只有5条消息,您也可以看到差异:

 [x] Sent 'Hello World!' 1428467734962
 [*] Waiting for messages. To exit press CTRL+C
 [x] Sent 'Hello World!' 1428467734963
1428467734965
 [x] Received 'Hello World!' 1
 [x] Sent 'Hello World!' 1428467734965
 [x] Sent 'Hello World!' 1428467734965
 [x] Sent 'Hello World!' 1428467734966
 [x] Sent 'Hello World!' 1428467734966
*** done
1428467735004
 [x] Received 'Hello World!' 2
1428467735005
 [x] Received 'Hello World!' 3
1428467735005
 [x] Received 'Hello World!' 4
1428467735005
 [x] Received 'Hello World!' 5