我正在使用Socket运行一个Express.js应用程序。IO的聊天网络应用程序 我在24小时内随机得到了5次以下错误。 节点进程永远被包装起来,并立即重新启动自己。

问题是重新启动Express会把我的用户赶出他们的房间 没有人希望这样。

web服务器通过HAProxy代理。插座不存在稳定性问题, 只是使用websockets和flashsockets传输。 我不能故意复制这个。

这是节点v0.10.11的错误:

    events.js:72
            throw er; // Unhandled 'error' event
                  ^
    Error: read ECONNRESET     //alternatively it s a 'write'
        at errnoException (net.js:900:11)
        at TCP.onread (net.js:555:19)
    error: Forever detected script exited with code: 8
    error: Forever restarting script for 2 time

编辑(2013-07-22)

增加了两个socket。IO客户端错误处理程序和未捕获的异常处理程序。 这个似乎捕获了错误:

    process.on('uncaughtException', function (err) {
      console.error(err.stack);
      console.log("Node NOT Exiting...");
    });

所以我怀疑这不是插座。发送HTTP请求到另一个服务器 或者MySQL/Redis连接。问题在于错误堆栈 不能帮我找出我的代码问题。以下是日志输出:

    Error: read ECONNRESET
        at errnoException (net.js:900:11)
        at TCP.onread (net.js:555:19)

我怎么知道是什么引起的呢?我如何从错误中得到更多?

好吧,不是很啰嗦,但这里是与朗约翰的堆栈跟踪:

    Exception caught: Error ECONNRESET
    { [Error: read ECONNRESET]
      code: 'ECONNRESET',
      errno: 'ECONNRESET',
      syscall: 'read',
      __cached_trace__:
       [ { receiver: [Object],
           fun: [Function: errnoException],
           pos: 22930 },
         { receiver: [Object], fun: [Function: onread], pos: 14545 },
         {},
         { receiver: [Object],
           fun: [Function: fireErrorCallbacks],
           pos: 11672 },
         { receiver: [Object], fun: [Function], pos: 12329 },
         { receiver: [Object], fun: [Function: onread], pos: 14536 } ],
      __previous__:
       { [Error]
         id: 1061835,
         location: 'fireErrorCallbacks (net.js:439)',
         __location__: 'process.nextTick',
         __previous__: null,
         __trace_count__: 1,
         __cached_trace__: [ [Object], [Object], [Object] ] } }

这里我提供了flash套接字策略文件:

    net = require("net")
    net.createServer( (socket) =>
      socket.write("<?xml version=\"1.0\"?>\n")
      socket.write("<!DOCTYPE cross-domain-policy SYSTEM \"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd\">\n")
      socket.write("<cross-domain-policy>\n")
      socket.write("<allow-access-from domain=\"*\" to-ports=\"*\"/>\n")
      socket.write("</cross-domain-policy>\n")
      socket.end()
    ).listen(843)

这是原因吗?


当前回答

是的,您提供的策略文件肯定会导致崩溃。

重复一下,只需在代码中添加一个延迟:

net.createServer( function(socket) 
{
    for (i=0; i<1000000000; i++) ;
    socket.write("<?xml version=\"1.0\"?>\n");
…

并通过Telnet方式连接到该端口。如果在延迟过期之前断开telnet连接,当socket时将会出现崩溃(未捕获异常)。Write抛出错误。

为了避免这里的崩溃,只需在读写套接字之前添加一个错误处理程序:

net.createServer(function(socket)
{
    for(i=0; i<1000000000; i++);
    socket.on('error', function(error) { console.error("error", error); });
    socket.write("<?xml version=\"1.0\"?>\n");
}

当您尝试上面的断开连接时,您只会得到一条日志消息,而不是崩溃。

当你完成时,记得删除延迟。

其他回答

我通过简单地连接到另一个网络解决了这个问题。这是可能出现的问题之一。

如上所述,ECONNRESET意味着TCP会话突然关闭连接的末端。

您的互联网连接可能阻止您连接到某些服务器。在我的例子中,我试图连接到mLab(托管MongoDB数据库的云数据库服务)。我的网络服务提供商屏蔽了它。

您可能已经猜到了:这是一个连接错误。

ECONNRESET意思是TCP会话的另一端突然关闭了它的连接端。这很可能是由于一个或多个应用程序协议错误。您可以查看API服务器日志,看看它是否抱怨了什么。

但是因为你也在寻找一种方法来检查错误并调试这个问题,你应该看看“如何调试NodeJS中的套接字挂起错误?”这篇文章是在stackoverflow上发布的,与一个类似的问题有关。

快速和肮脏的开发解决方案:

使用longjohn,您将获得包含异步操作的长堆栈跟踪。

干净正确的解决方案: 从技术上讲,在node中,每当你发出'error'事件而没有人侦听它时,它就会抛出。为了使它不抛出,在它上面放置一个侦听器并自己处理它。这样,您就可以用更多的信息记录错误。

要为一组调用使用一个侦听器,您可以使用域并在运行时捕获其他错误。确保与http(服务器/客户端)相关的每个异步操作与代码的其他部分相比处于不同的域上下文中,域将自动侦听错误事件并将其传播到自己的处理程序。因此,您只侦听该处理程序并获得错误数据。你还可以免费获得更多信息。

编辑(2013-07-22)

正如我上面所写的:

ECONNRESET意思是TCP会话的另一端突然关闭了它的连接端。这很可能是由于一个或多个应用程序协议错误。您可以查看API服务器日志,看看它是否抱怨了什么。

也有可能是这样的情况:在任意时间,另一端过载,结果只是终止连接。如果是这样的话,这取决于你连接的到底是什么……

但有一件事是肯定的:你的TCP连接上确实有一个读取错误,导致异常。您可以通过查看您在编辑中发布的错误代码来确认这一点。

我遇到过类似的问题,在升级Node后,应用程序开始出错。我相信这可以追溯到Node v0.9.10版本的这一项:

net:不压制ECONNRESET (Ben Noordhuis)

以前的版本不会在客户端中断时出错。来自客户端的连接中断会在Node中抛出错误ECONNRESET。我相信这是Node的预期功能,因此修复(至少对我来说)是处理错误,我相信您在unCaught异常中做到了这一点。虽然我在网上处理。套接字处理程序。

你可以这样演示:

创建一个简单的套接字服务器,并获得Node v0.9.9和v0.9.10。

require('net')
    .createServer( function(socket) 
    {
           // no nothing
    })
    .listen(21, function()
     {
           console.log('Socket ON')
    })

使用v0.9.9启动它,然后尝试通过FTP传输到此服务器。我使用FTP和端口21只是因为我在Windows上,有一个FTP客户端,但没有telnet客户端方便。

然后从客户端断开连接。(我正在按Ctrl-C)

在使用Node v0.9.9时应该看到NO ERROR,在使用Node v.0.9.10及更高版本时应该看到ERROR。

在生产环境中,我使用v.0.10。它仍然会给出错误。同样,我认为这是有意的,解决方案是处理代码中的错误。

一个简单的tcp服务器,我提供的flash策略文件导致了这个问题。我现在可以使用处理程序捕获错误:

# serving the flash policy file
net = require("net")

net.createServer((socket) =>
  //just added
  socket.on("error", (err) =>
    console.log("Caught flash policy server socket error: ")
    console.log(err.stack)
  )

  socket.write("<?xml version=\"1.0\"?>\n")
  socket.write("<!DOCTYPE cross-domain-policy SYSTEM \"http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd\">\n")
  socket.write("<cross-domain-policy>\n")
  socket.write("<allow-access-from domain=\"*\" to-ports=\"*\"/>\n")
  socket.write("</cross-domain-policy>\n")
  socket.end()
).listen(843)

我也面临着同样的问题,但我通过以下方式缓解了它:

server.timeout = 0;

server.listen之前。服务器是一个HTTP服务器。根据API文档,默认超时时间为2分钟。