是什么导致 amqp.node 从 RabbitMQ 服务器获取 ECONNRESET?

bpi*_*lva 4 rabbitmq node.js

我有一个在 Windows 8 环境中运行的 RabbitMQ(默认配置)实例。我的节点版本是 5.1.0,我正在尝试使用amqp.node库在它们之间建立连接以传递消息。

当我尝试示例代码时:

var q = 'tasks';

function bail(err) {
  console.error(err);
  process.exit(1);
}

// Publisher
function publisher(conn) {
  conn.createChannel(on_open);
  function on_open(err, ch) {
    if (err != null) bail(err);
    ch.assertQueue(q);
    ch.sendToQueue(q, new Buffer('something to do'));
  }
}

// Consumer
function consumer(conn) {
  var ok = conn.createChannel(on_open);
  function on_open(err, ch) {
    if (err != null) bail(err);
    ch.assertQueue(q);
    ch.consume(q, function(msg) {
      if (msg !== null) {
        console.log(msg.content.toString());
        ch.ack(msg);
      }
    });
  }
}

require('amqplib/callback_api')
  .connect('amqp://guest:guest@localhost:5672', function(err, conn) {
    if (err != null) bail(err);
    consumer(conn);
    publisher(conn);        
  });
Run Code Online (Sandbox Code Playgroud)

我得到它工作正常。

但是,如果我将此代码(确切地说是这样)移动到我的项目中,则会出现此错误:

ECCONRESET 系统调用:读取。

我的应用程序使用 express.js 和 oauth2.0 运行。即使我将代码放在任何其他语句和模块的要求之前,它也不起作用。

我搜索了这个错误,发现了一些与负载平衡相关的问题,但我在本地运行它并且示例代码工作正常。

我发现的另一个问题可能与 TCP 连接有关,我将 RabbitMQ 服务器配置文件中的握手超时选项更改为 10000 毫秒,但没有任何改变。

我对来宾用户使用相同的 url:amqp://guest:guest@localhost:5672,它适用于示例代码。

RabbitMQ 的日志显示连接已完成,但几秒钟后,它指出连接意外关闭:

=INFO REPORT==== 24-Nov-2015::18:09:52 ===
accepting AMQP connection <0.2644.0> (127.0.0.1:51866 -> 127.0.0.1:5672)

=ERROR REPORT==== 24-Nov-2015::18:10:12 ===
closing AMQP connection <0.2644.0> (127.0.0.1:51866 -> 127.0.0.1:5672):
{handshake_timeout,frame_header}
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:amqp.node 和其他断开与服务器连接的库之间是否存在冲突?我该如何调试?

Suk*_*gat 7

此错误与连接和通道有关。因此,在您的代码中,您正在创建连接和通道,但并未关闭它们。当没有时会产生此错误(ECONNRESET)。连接和通道限制已用完 RabbitMQ 将停止接受新的网络连接。关闭通道和连接将解决此错误。示例代码:

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

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

        return ok.then(function(_qok) {
            ch.sendToQueue(q, new Buffer(msg), {deliveryMode: true});
            console.log(" [x] Sent '%s'", msg);
            return ch.close();
        });
    })).ensure(function() {
        conn.close();
    });
})
.then(null, console.warn);
Run Code Online (Sandbox Code Playgroud)


Der*_*ley 4

ECONNRESET 通常是一个网络错误,这意味着它与尝试建立的 TCP/IP 连接被强制断开。

您的项目的运行方式可能会阻止其正确打开 TCP/IP 连接,或者遇到防火墙或其他问题。

当用户名和密码错误时,我也看到过此错误。我强烈建议您设置一个新的用户名和密码,并授予该用户对相关虚拟主机(本例中为默认虚拟主机)的正确权限。

除此之外......有时需要一些代码来找出导致问题的原因。如果您在复制并粘贴到实际项目中时没有看到此问题,则项目中可能存在其他问题导致其无法工作。

...

PS 我建议不要直接使用 amqplib 。它是一个很棒的驱动程序,但在它之上还有更好(更友好)的 API 层,让生活变得更轻松。例如,我最喜欢的是wascally,它在底层使用 amqplib。我在http://RabbitMQ4Devs.com上录制了有关这一切的截屏视频