节点js ECONNRESET

时间:2013-06-21 23:49:22

标签: node.js sockets tcp express

我正在运行带有socket.io的Express js应用程序进行聊天    webapp和我在5次期间随机获得以下错误    24小时。节点进程永远包装并重新启动    本身就是。

问题是重启快递会将我的用户踢出他们的房间    没有人想要那个。

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...");
});

所以我怀疑它不是socket.io问题,而是对我做的另一台服务器的http请求或mysql / redis连接。问题是错误堆栈无法帮助我识别代码问题。这是日志输出:

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

我怎么知道是什么原因造成的?如何从错误中获得更多信息?

好的,不是很冗长,但这里是带有“longjohn”的堆栈跟踪:

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)

这可能是原因吗?

16 个答案:

答案 0 :(得分:217)

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

“ECONNRESET”表示TCP对话的另一端突然关闭了它的连接结束。这很可能是由于一个或多个应用程序协议错误。您可以查看API服务器日志,看看它是否有抱怨。

但是既然你也在寻找一种检查错误并可能调试问题的方法,那么你应该看一下发布在stackoverflow上的How to debug a socket hang up error in NodeJS?。一个类似的问题。

  

快速而肮脏的开发解决方案

     

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

     

清洁且正确的解决方案:     从技术上讲,在节点中,只要you emit an 'error' event and no one listens to it, it will throw。为了使它不被抛出,请在其上放置一个监听器并自己处理它。这样,您可以使用更多信息记录错误。

     

要为一组调用创建一个侦听器,您可以使用domains并在运行时捕获其他错误。确保与http(服务器/客户端)相关的每个异步操作与代码的其他部分相比处于不同的domain上下文中,域将自动侦听error事件并将其传播到它自己的处理所以你只听那个处理程序并获取错误数据。 You also get more information for free.

编辑(2013-07-22)

正如我上面所写:

  

“ECONNRESET”表示TCP对话的另一端突然关闭了它的连接结束。这很可能是由于一个或多个应用程序协议错误。您可以查看API服务器日志,看看它是否有抱怨。

也可能是这种情况:在随机时间,另一方过载并且因此简单地杀死连接。如果是这种情况,取决于您正在连接的内容......

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

答案 1 :(得分:34)

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

# 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)

答案 2 :(得分:26)

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

  • net:不要压制ECONNRESET(Ben Noordhuis)

以前的版本不会在客户端中断时出错。来自客户端的连接中断会在Node中引发错误ECONNRESET。我相信这是Node的功能,所以修复(至少对我来说)是处理错误,我相信你在unCaught异常中做了。虽然我在net.socket处理程序中处理它。

你可以证明这一点:

创建一个简单的套接字服务器并获取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。一些东西,它仍然给出了错误。同样,我认为这是有意的,解决方案是处理代码中的错误。

答案 3 :(得分:14)

我遇到了同样的问题,但我通过放置来缓解它:

server.timeout = 0;
server.listen之前

server是这里的HTTP服务器。根据{{​​3}},默认超时为2分钟。

答案 4 :(得分:13)

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

答案 5 :(得分:7)

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

要重复,只需在代码中添加延迟:

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() { console.log("error"); });
  socket.write("<?xml version=\"1.0\"?>\n")

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

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

答案 6 :(得分:6)

另一种可能的情况(但很少见)可能是您有服务器到服务器的通信并且已将server.maxConnections设置为非常低的值。

在节点的核心库net.js中,它将调用clientHandle.close(),这也会导致错误ECONNRESET:

if (self.maxConnections && self._connections >= self.maxConnections) {
  clientHandle.close(); // causes ECONNRESET on the other end
  return;
}

答案 7 :(得分:4)

我在开发过程中也遇到ECONNRESET错误,我解决它的方式是使用nodemon启动我的服务器,只需使用"node server.js"启动我的服务器修复我的问题。

这很奇怪,但它对我有用,现在我再也看不到ECONNRESET错误了。

答案 8 :(得分:3)

至少在我的用例中,我才发现这一点。

我得到ECONNRESET。事实证明,我的客户端的设置方式是通过API调用快速击中服务器很多次-只需击中端点一次。

当我解决该问题时,错误消失了。

答案 9 :(得分:2)

我通过以下方法解决了这个问题:

  • 关闭我的wifi /以太网连接,然后再打开。
  • 我在终端输入了npm update以更新npm。
  • 我试图退出会话并再次登录

在那之后,我尝试了相同的npm命令,但是好了,它解决了。我不确定是否那么简单。

我正在使用CENTOS 7

答案 10 :(得分:1)

我通过连接到不同的网络解决了这个问题。这是可能存在的问题之一。

如上所述, ECONNRESET 表示TCP会话突然关闭其连接结束。

您的互联网连接可能阻止您连接到某些服务器。就我而言,我试图连接到mLab(托管MongoDB数据库的云数据库服务)。我的ISP阻止了它。

答案 11 :(得分:1)

我也有这个错误,经过几天的调试和分析后能够解决它:

我的解决方案

对我来说VirtualBox(对于Docker)是问题所在。我在我的VM上配置了端口转发,只在转发的端口上发生了错误。

一般性结论

以下观察可能会为您节省您不得不投入的工作天数:

  • 对我来说,问题只发生在一个端口上从localhost到localhost的连接上。 - &GT;检查更改任何这些常量可以解决问题。
  • 对我来说问题只发生在我的机器上 - &gt;让其他人试一试。
  • 对我来说,这个问题只是在一段时间后才会发生,而且无法可靠地再现
  • 我的问题无法通过任何节点或表达(调试)工具进行检查。 - &GT;不要在这个上浪费时间

<强> - &GT;弄清楚是否有什么东西搞乱你的网络(设置),如虚拟机,防火墙等,这可能是导致问题的原因。

答案 12 :(得分:1)

ECONNRESET 当服务器端关闭 TCP 连接并且您对服务器的请求没有得到满足时发生。服务器以连接的消息作为响应,您指的是无效连接。

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

假设您已启用客户端和服务器之间的保持活动连接。保持活动超时配置为 15 秒。这意味着如果 keep-alive 空闲 15 秒,它将发送连接关闭请求。所以 15 秒后,服务器告诉客户端关闭连接。 但是,当服务器发送此请求时,客户端正在向服务器端发送一个已经在飞行中的新请求。由于此连接现在无效,服务器将拒绝 ECONNRESET 错误。所以出现问题是由于对服务器端的请求较少。所以请禁用keep-alive,它会正常工作。

答案 13 :(得分:0)

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

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

我希望这会对你有所帮助!

答案 14 :(得分:0)

我遇到了同样的问题,看来Node.js版本是问题所在。

我安装了以前版本的Node.js(10.14.2),使用nvm一切正常(允许您安装多个版本的Node.js并快速从一个版本切换到另一个版本)。

这不是一个“干净”的解决方案,但可以为您提供临时服务。

答案 15 :(得分:0)

Node JS 套接字是非阻塞 io。考虑使用来自其他来源的非阻塞 io 连接。例如,如果您使用带有 node 的阻塞 Java 套接字,它只会工作几秒钟,之后将出现错误。通过实现非阻塞连接来缓解这种情况,即带有选择器的 socketchannel。

相关问题