节点js ECONNRESET

Sam*_*son 266 sockets tcp node.js express

我正在运行带有socket.io的Express js应用程序用于聊天webapp,并且我在24小时内随机获得以下错误5次左右.节点进程永远包装,并立即重新启动.

问题是重新启动快速将我的用户踢出他们的房间而没人想要.

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
Run Code Online (Sandbox Code Playgroud)

编辑(2013-07-22)

添加了socket.io客户端错误处理程序和未捕获的异常处理程序.似乎这个捕获了错误:

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

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

Error: read ECONNRESET
    at errnoException (net.js:900:11)
    at TCP.onread (net.js:555:19)
Run Code Online (Sandbox Code Playgroud)

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

好吧,不是很冗长,但这里是带有"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] ] } }
Run Code Online (Sandbox Code Playgroud)

在这里,我提供了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)
Run Code Online (Sandbox Code Playgroud)

这可能是原因吗?

e-s*_*shi 237

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

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

但是既然你也在寻找一种检查错误并可能调试问题的方法,你应该看一下" 如何调试NodeJS中的套接字挂起错误? ",这是在stackoverflow上发布的,与一个类似的问题有关.

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

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

清晰且正确的解决方案:从技术上讲,在节点中,无论何时发出'error'事件并且没有人收听它,它都会抛出.为了使它不被抛出,请在其上放置一个监听器并自己处理它.这样,您可以使用更多信息记录错误.

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

编辑(2013-07-22)

正如我上面写的:

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

也可能是这种情况:在随机时间,另一方面超载并且因此简单地杀死连接.如果是这种情况,取决于你正在连接的是什么......

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

  • @EJP 我“突然”写作是有充分理由的。错误(不是警告)表明连接已被对等方重置。**远程对等方强行关闭了现有连接。** 意外的强制关闭是突然的!(如果远程机器上的对等应用程序突然停止、机器重新启动或对等应用程序在远程套接字上使用“硬关闭”,这通常会导致。如果连接因“保持活动”活动而中断,也可能导致此错误在一个或多个操作正在进行时检测到故障……这些操作和后续操作将失败。) (4认同)
  • 当我从浏览器(Chrome)批量同时发送约100个API调用进行测试时,会引发此错误。我以为Chrome一定会变得超负荷并杀死某些连接... @Samson-在自己的域中处理每个请求并在不重新启动服务器的情况下捕获域错误是怎么回事? (2认同)
  • @supershnee您几乎应该始终在发生未捕获的异常后重新启动服务器,因为您的数据,应用程序和node.js本身处于未知状态。发生异常后继续操作会给您的数据带来风险。如果您想了解更多信息,请查看[Node上的文档](https://nodejs.org/docs/latest/api/process.html#process_event_uncaughtexception)或[Node上的域文档](https:// nodejs .org / api / domain.html)。 (2认同)

Sam*_*son 36

我用于提供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)
Run Code Online (Sandbox Code Playgroud)

  • 代码有什么问题吗?我应该在写入之前检查套接字是否可写吗? (2认同)
  • 我总是在错误处理程序中调用`socket.destroy()`来确保.遗憾的是,我找不到文档是否需要,但它不会发出错误. (2认同)

Joh*_*ams 26

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

  • 网:不要压制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')
    })
Run Code Online (Sandbox Code Playgroud)

使用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.一些东西,它仍然给出了错误.同样,我认为这是有意的,解决方案是处理代码中的错误.

  • 谢谢,我自己钉了它!重要的是不要让错误传播到uncaughtException,因为它会使整个应用程序不稳定.例如,在捕获大约10个ECONNRESET错误之后,服务器有时会变得没有响应(只是冻结并且没有处理任何连接) (3认同)
  • 还知道节点版本更改不再抑制错误,但是看到每个版本都出现这么多问题并得到解决,我宁愿选择最新版本。顺便说一句,我现在正在使用 V0.10.13 (2认同)

小智 15

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

  • 奇怪的是,我正在寻找这个旧问题的新答案 - 但这很好,谢谢 (3认同)

小智 13

我遇到了同样的问题,但我放置了以下内容:

server.timeout = 0;
Run Code Online (Sandbox Code Playgroud)

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

  • 这不是解决方案,而是一种快速修复程序,它可以在不引发错误的情况下中断事情。 (5认同)

hap*_*set 9

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

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

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


小智 9

当服务器端关闭 TCP 连接并且您对服务器的请求未得到满足时,ECONNRESET就会发生。服务器响应一条消息,表明该连接,您指的是无效连接。

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

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


Joa*_*son 7

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

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

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

...并用于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")
Run Code Online (Sandbox Code Playgroud)

当您尝试上述断开连接时,您只需获取日志消息而不是崩溃.

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


You*_*sef 7

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

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

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


Wao*_*aog 6

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

我的解决方案

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

一般结论

以下观察结果可以为您节省我不得不投入的工作天数:

  • 对我来说,问题只发生在一个端口上从本地主机到本地主机的连接上。-> 检查更改这些常量中的任何一个都可以解决问题。
  • 对我来说,问题只发生在我的机器上 -> 让其他人试试。
  • 对我来说,问题只发生在一段时间后,无法可靠地重现
  • 无法使用任何节点或表达(调试)工具检查我的问题。-> 不要在这上面浪费时间

-> 找出您的网络(-设置)是否有问题,例如虚拟机、防火墙等,这可能是问题的原因。


And*_*eng 5

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

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


muh*_*yab 5

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

  • 关闭我的 wifi/以太网连接并打开。
  • npm update在终端中输入: 来更新 npm。
  • 我尝试退出会话并重新登录

之后我尝试了相同的 npm 命令,幸运的是它成功了。我不确定事情有这么简单。

我使用的是CENTOS 7


Vik*_*ikR 5

我刚刚弄清楚了这一点,至少在我的用例中是这样。

我正在得到ECONNRESET。事实证明,按照我的客户端设置方式,它会非常快速地通过 API 调用多次访问服务器,而且只需要访问端点一次。

当我解决这个问题时,错误就消失了。