如何在 Node.js 中调试错误 ECONNRESET?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17245881/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 14:52:08  来源:igfitidea点击:

How do I debug error ECONNRESET in Node.js?

node.jssocketstcpexpress

提问by Samson

I'm running an Express.js application using Socket.io for a chat webapp and I get the following error randomly around 5 times during 24h. The node process is wrapped in forever and it restarts itself immediately.

我正在使用 Socket.io 运行 Express.js 应用程序作为聊天 web 应用程序,我在 24 小时内随机收到以下错误大约 5 次。节点进程被永远包裹起来,它会立即重新启动。

The problem is that restarting Express kicks my users out of their rooms and nobody wants that.

问题是重新启动 Express 会将我的用户踢出他们的房间,而没有人想要这样。

The web server is proxied by HAProxy. There are no socket stability issues, just using websockets and flashsockets transports. I cannot reproduce this on purpose.

Web 服务器由 HAProxy 代理。没有套接字稳定性问题,只需使用 websockets 和 flashsockets 传输。我不能故意复制这个。

This is the error with Node v0.10.11:

这是 Node 的错误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

EDIT (2013-07-22)

编辑 (2013-07-22)

Added both socket.io client error handler and the uncaught exception handler. Seems that this one catches the error:

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

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

So I suspect it's not a Socket.io issue but an HTTP request to another server that I do or a MySQL/Redis connection. The problem is that the error stack doesn't help me identify my code issue. Here is the log output:

所以我怀疑这不是 Socket.io 问题,而是对我所做的另一台服务器或 MySQL/Redis 连接的 HTTP 请求。问题是错误堆栈不能帮助我识别我的代码问题。这是日志输出:

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

How do I know what causes this? How do I get more out of the error?

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

Ok, not very verbose but here's the stacktrace with Longjohn:

好的,不是很冗长,但这是 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] ] } }

Here I serve the flash socket policy file:

在这里,我提供闪存套接字策略文件:

    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)

Can this be the cause?

这可能是原因吗?

采纳答案by Samson

A simple tcp server I had for serving the flash policy file was causing this. I can now catch the error using a handler:

我用于提供闪存策略文件的一个简单的 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)

回答by e-sushi

You might have guessed it already: it's a connection error.

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

"ECONNRESET"means the other side of the TCP conversation abruptly closed its end of the connection. This is most probably due to one or more application protocol errors. You could look at the API server logs to see if it complains about something.

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

But since you are also looking for a way to check the error and potentially debug the problem, you should take a look at "How to debug a socket hang up error in NodeJS?"which was posted at stackoverflow in relation to an alike question.

但是,由于您还在寻找一种方法来检查错误并可能调试问题,因此您应该查看如何在 NodeJS 中调试套接字挂断错误?,它发布在 stackoverflow 上,与一个类似的问题相关。

Quick and dirty solution for development:

Use longjohn, you get long stack traces that will contain the async operations.

Clean and correct solution: Technically, in node, whenever you emit an 'error'event and no one listens to it, it will throw. To make it not throw, put a listener on it and handle it yourself. That way you can log the error with more information.

To have one listener for a group of calls you can use domainsand also catch other errors on runtime. Make sure each async operation related to http(Server/Client) is in different domaincontext comparing to the other parts of the code, the domain will automatically listen to the errorevents and will propagate it to it's own handler. So you only listen to that handler and get the error data. You also get more information for free.

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

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

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

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

EDIT (2013-07-22)

编辑 (2013-07-22)

As I wrote above:

正如我上面写的:

"ECONNRESET"means the other side of the TCP conversation abruptly closed its end of the connection. This is most probably due to one or more application protocol errors. You could look at the API server logs to see if it complains about something.

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

What could also be the case: at random times, the other side is overloaded and simply kills the connection as a result. If that's the case, depends on what you're connecting to exactly…

也可能是这种情况:在随机时间,另一端过载并因此简单地终止连接。如果是这种情况,则取决于您确切连接的对象……

But one thing's for sure: you indeed have a read error on your TCP connection which causes the exception. You can see that by looking at the error code you posted in your edit, which confirms it.

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

回答by John Williams

I had a similar problem where apps started erroring out after an upgrade of Node. I believe this can be traced back to Node release v0.9.10 this item:

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

  • net: don't suppress ECONNRESET (Ben Noordhuis)
  • 网:不要压制 ECONNRESET (Ben Noordhuis)

Previous versions wouldn't error out on interruptions from the client. A break in the connection from the client throws the error ECONNRESET in Node. I believe this is intended functionality for Node, so the fix (at least for me) was to handle the error, which I believe you did in unCaught exceptions. Although I handle it in the net.socket handler.

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

You can demonstrate this:

你可以证明这一点:

Make a simple socket server and get Node v0.9.9 and v0.9.10.

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

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

Start it up using v0.9.9 and then attempt to FTP to this server. I'm using FTP and port 21 only because I'm on Windows and have an FTP client, but no telnet client handy.

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

Then from the client side, just break the connection. (I'm just doing Ctrl-C)

然后从客户端,断开连接。(我只是在做 Ctrl-C)

You should see NO ERROR when using Node v0.9.9, and ERROR when using Node v.0.9.10 and up.

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

In production, I use v.0.10. something and it still gives the error. Again, I think this is intended and the solution is to handle the error in your code.

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

回答by stainful

Had the same problem today. After some research i found a very useful --abort-on-uncaught-exceptionnode.js option. Not only it provides much more verbose and useful error stack trace, but also saves core file on application crash allowing further debug.

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

回答by Ashish Kaila

I was facing the same issue but I mitigated it by placing:

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

server.timeout = 0;

before server.listen. serveris an HTTP server here. The default timeout is 2 minutes as per the API documentation.

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

回答by happy_marmoset

Another possible case (but rare) could be if you have server to server communications and have set server.maxConnectionsto a very low value.

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

In node's core lib net.jsit will call clientHandle.close()which will also cause error ECONNRESET:

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

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

回答by Joachim Isaksson

Yes, your serving of the policy file can definitely cause the crash.

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

To repeat, just add a delay to your code:

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

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

… and use telnetto connect to the port. If you disconnect telnet before the delay has expired, you'll get a crash (uncaught exception) when socket.write throws an error.

...并用于telnet连接到端口。如果您在延迟到期之前断开 telnet 连接,那么当 socket.write 抛出错误时,您将发生崩溃(未捕获的异常)。

To avoid the crash here, just add an error handler before reading/writing the socket:

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

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

When you try the above disconnect, you'll just get a log message instead of a crash.

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

And when you're done, remember to remove the delay.

完成后,请记住删除延迟。

回答by Andrew Lam

I also get ECONNRESET error during my development, the way I solve it is by notusing nodemon to start my server, just use "node server.js"to start my server fixed my problem.

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

It's weird, but it worked for me, now I never see the ECONNRESET error again.

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

回答by Waog

I had this Error too and was able to solve it after days of debugging and analysis:

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

my solution

我的解决方案

For me VirtualBox (for Docker) was the Problem. I had Port Forwarding configured on my VM and the error only occured on the forwarded port.

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

general conclusions

一般结论

The following observations may save you days of work I had to invest:

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

  • For me the problem only occurred on connections from localhost to localhost on one port. -> check changing any of these constants solves the problem.
  • For me the problem only occurred on my machine -> let someone else try it.
  • For me the problem only occurred after a while and couldn't be reproduced reliably
  • My Problem couldn't be inspected with any of nodes or expresses (debug-)tools. -> don't waste time on this
  • 对我来说,问题只发生在一个端口上从本地主机到本地主机的连接上。-> 检查更改这些常量中的任何一个都可以解决问题。
  • 对我来说,问题只发生在我的机器上 -> 让其他人试试。
  • 对我来说,问题只发生在一段时间后,无法可靠地重现
  • 无法使用任何节点或表达(调试)工具检查我的问题。-> 不要在这上面浪费时间

-> figure out if something is messing around with your network (-settings), like VMs, Firewalls etc., this is probably the cause of the problem.

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

回答by muhammad tayyab

I had resolved this problem by:

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

  • Turning off my wifi/ethernet connection and turn on.
  • I typed: npm updatein terminal to update npm.
  • I tried to log out from the session and log in again
  • 关闭我的 wifi/以太网连接并打开。
  • 我输入:npm update在终端更新 npm。
  • 我试图从会话中注销并重新登录

After that I tried the same npm command and the good thing was it worked out. I wasn't sure it is that simple.

之后我尝试了相同的 npm 命令,好消息是它成功了。我不确定是不是这么简单。

I am using CENTOS 7

我正在使用 CENTOS 7