我正在使用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)

这是原因吗?


当前回答

一个简单的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)

其他回答

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

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

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

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

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

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

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

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

编辑(2013-07-22)

正如我上面所写的:

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

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

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

尝试将这些选项添加到socket.io:

const options = { transports: ['websocket'], pingTimeout: 3000, pingInterval: 5000 };

我希望这对你有帮助!

当服务器端关闭TCP连接并且您对服务器的请求没有得到满足时,将发生ECONNRESET。服务器响应消息,表明您引用的连接无效。

为什么服务器发送无效连接的请求?

Suppose you have enabled a keep-alive connection between client and server. The keep-alive timeout is configured to 15 seconds. This means that if keep-alive is idle for 15 seconds, it will send connection close request. So after 15 seconds, server tells the client to close the connection. BUT, when server is sending this request, client is sending a new request which is already on flight to the server end. Since this connection is invalid now, server will reject with ECONNRESET error. So the problem occurs due to fewer requests to the server end. So please disable keep-alive and it will work fine.

今天也遇到了同样的问题。 经过一些研究,我发现了一个非常有用的——abort-on-uncaught-exception node.js选项。它不仅提供了更详细和有用的错误堆栈跟踪,而且还保存了应用程序崩溃时的核心文件,允许进一步调试。