如何在Node.js中调试ECONNRESET错误?
如何在Node.js中调试ECONNRESET错误?
我正在运行一个使用Socket.io的Express.js应用程序,用于聊天网页应用。在24小时内,我随机遇到以下错误大约5次。Node进程被永久包装起来,它会立即重新启动。问题在于重新启动Express会让我的用户退出他们的聊天室,而没有人想要这样。Web服务器由HAProxy代理。没有任何socket稳定性问题,只是使用了websocket和flashsocket传输。我无法有意地再现这个错误。这是使用Node v0.10.11
的错误:\n
events.js:72 throw er; // Unhandled 'error' event ^ Error: read ECONNRESET // 或者是'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
\n编辑(2013-07-22)\n添加了socket.io客户端错误处理程序和未捕获的异常处理程序。\n似乎这个可以捕获错误:\n
process.on('uncaughtException', function (err) { console.error(err.stack); console.log("Node NOT Exiting..."); });
\n所以我怀疑这不是Socket.io的问题,而是我对另一个服务器的HTTP请求或MySQL/Redis连接。问题在于错误堆栈并没有帮助我确定我的代码问题。这是日志输出:\n
Error: read ECONNRESET at errnoException (net.js:900:11) at TCP.onread (net.js:555:19)
\n我如何知道是什么原因导致这个错误?我如何从错误中获得更多信息?\n好的,不是很详细,但是这是使用Longjohn的堆栈跟踪:\n
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] ] } }
\n在这里我提供flash socket策略文件:\n
net = require("net") net.createServer( (socket) => socket.write("\n") socket.write("\n") socket.write("\n") socket.write(" \n") socket.end() ).listen(843)\n") socket.write("
\n这可能是原因吗?
问题的出现原因是因为在Node版本v0.9.10中,当客户端断开连接时,会抛出错误ECONNRESET。之前的版本不会因为客户端的中断而报错。我认为这是Node的预期功能,所以解决方法是处理这个错误,我在net.socket处理程序中进行了处理。
解决方法是在代码中处理错误,比如在未捕获的异常处理程序中。您可以通过以下步骤来演示:
1. 创建一个简单的socket服务器,并使用Node v0.9.9和v0.9.10来启动它:
require('net') .createServer( function(socket) { // do nothing }) .listen(21, function() { console.log('Socket ON') })
2. 使用v0.9.9来启动服务器,然后尝试通过FTP连接到此服务器。您可以使用FTP和端口21,只是因为我在Windows上有一个FTP客户端,但没有telnet客户端方便。
3. 然后从客户端断开连接(我只是按Ctrl-C)。
4. 当使用Node v0.9.9时,您不应该看到任何错误,当使用Node v.0.9.10及更高版本时,您将看到错误。
在生产环境中,我使用的是v0.10.x版本,仍然会出现这个错误。所以解决办法是在代码中处理这个错误。
感谢您的阅读,我自己解决了这个问题!重要的是不要让错误传播到未捕获的异常,因为这会使整个应用程序不稳定。例如,在捕获了大约10个ECONNRESET错误之后,服务器有时会变得无响应(冻结并且不处理任何连接)。
我也了解到了Node版本更改,不再抑制这个错误,但是考虑到每个版本都会出现很多问题并且得到解决,我更倾向于使用最新的版本。我现在正在使用V0.10.13版本。
问题:如何调试Node.js中的ECONNRESET错误?
原因:这个问题是由于我为提供Flash策略文件而创建的简单TCP服务器引起的。现在我可以使用处理程序来捕获错误。
解决方法:在错误处理程序中调用socket.destroy()来确保关闭socket。
以下是示例代码:
// serving the flash policy file const 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.destroy(); }); socket.write("\n"); socket.write("\n"); socket.write("\n"); socket.write(" \n"); socket.end(); }).listen(843);\n"); socket.write("
以上代码可以解决ECONNRESET错误,并确保安全关闭socket。
希望对你有所帮助!
"ECONNRESET"错误是由于TCP连接的另一端突然关闭连接引起的。这很可能是由于一个或多个应用程序协议错误。可以查看API服务器日志以查看是否有错误信息。为了检查错误并潜在地调试问题,可以参考在stackoverflow上发布的与类似问题相关的"如何调试NodeJS中的套接字挂起错误?"。
快速而不完整的开发解决方案:使用longjohn,它可以提供包含异步操作的长堆栈跟踪。
干净而正确的解决方案是,在Node中,每当发出一个"error"事件而没有任何监听器时,它将抛出错误。为了防止抛出错误,需要在其上添加一个监听器并自行处理。这样,可以记录包含更多信息的错误。
要为一组调用添加一个监听器,可以使用domain,并在运行时捕获其他错误。确保与代码的其他部分相比,每个与http(Server/Client)相关的异步操作都位于不同的domain上下文中,域将自动监听"error"事件并将其传播到自己的处理程序。因此,只需要监听该处理程序并获取错误数据。此外,还可以免费获得更多信息。
另外,"ECONNRESET"错误意味着TCP会话的另一端突然关闭了连接。这很可能是由于一个或多个应用程序协议错误。可以查看API服务器日志以查看是否有错误信息。
可能还有一种情况:在随机的时间,另一端过载并且简单地关闭连接。这取决于您连接到的确切内容...
但有一点是确定的:确实存在TCP连接的读取错误,这导致了异常。通过查看您在编辑中发布的错误代码,可以看到这一点。
它不一定意味着"突然关闭"。通常是由于向已经正常关闭的连接写入导致的。这将导致发出RST。
当我从浏览器(Chrome)批量发送大约100个API调用进行测试时,我会抛出此错误。我想象Chrome必须变得过载并终止一些连接... 在不重新启动服务器的情况下,为什么不能在自己的域中处理每个请求并捕获域错误?
几乎总是应该在未捕获的异常后重新启动服务器,因为您的数据、应用程序和Node.js本身处于未知状态。在异常后继续运行会将您的数据置于风险之中。如果想要了解更多信息,请查看Node关于进程的文档或Node关于域的文档。
这个错误在生产中出现吗?