我正在运行一个带有socket.io的Express js应用程序,用于一个聊天软件。 我在运行一个带有socket.io的Express js应用程序,用于聊天,但在24小时内我随机收到以下错误约5次。 24h.节点进程永远被包裹在其中,并立即重新启动 它自己立即重新启动。
问题是,重启快递会把我的用户从他们的房间里踢出去 没有人希望这样。
网络服务器是由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 socket策略文件。
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)
这可能是原因吗?
你可能已经猜到了:这是一个连接错误。
"ECONNRESET"意味着TCP对话的另一方突然关闭了其连接的一端。这很可能是由于一个或多个应用协议错误造成的。你可以看一下API服务器的日志,看看它是否抱怨了什么。
但由于你也在寻找一种检查错误和潜在调试问题的方法,你应该看看"如何调试NodeJS中的套接字挂起错误?",这是在stackoverflow上发布的与一个类似的问题有关的。
快速和肮脏的解决方案,用于开发。
使用longjohn,你会得到包含异步操作的长堆栈痕迹。
干净和正确的解决方案。 从技术上讲,在node中,只要你发出一个
'error'
事件而没有人监听它,它就会抛出。为了使它不被抛出,在它上面放一个监听器并自己处理它。这样,你就可以用更多的信息来记录错误。
要为一组调用设置一个监听器,你可以使用domains,也可以在运行时捕获其他错误。确保每个与http(Server/Client)相关的异步操作都在不同的domain上下文中,与代码的其他部分相比,该域将自动监听
error
事件,并将其传播到它自己的处理程序中。所以你只监听那个处理程序并获得错误数据。你还可以免费获得更多的信息。
编辑(2013-07-22)
正如我在上面写的。
"ECONNRESET"意味着TCP对话的另一方突然关闭了其连接的一端。这很可能是由于一个或多个应用协议错误造成的。你可以看一下API服务器的日志,看看它是否抱怨了什么。
也有可能是这样的情况:在随机的时候,另一方的负荷过重,并因此而简单地杀死了连接。如果是这种情况,要看你到底连接的是什么......
但有一点是肯定的:你的TCP连接上确实有一个读错,导致了异常。你可以通过查看你在编辑中发布的错误代码来了解,这就证实了这一点。
我有一个简单的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)
我有一个类似的问题,在升级Node后,应用程序开始出错。 我相信这可以追溯到Node发布的v0.9.10这个项目。
以前的版本不会在来自客户端的中断时出错。 来自客户端的连接中断会在Node中引发错误ECONNRESET。 我相信这是为Node设计的功能,所以修复方法(至少对我来说)是处理这个错误,我相信你在unCaughts异常中做了这个。 尽管我在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时,你应该看到没有错误,而在使用Node v.0.9.10及以上版本时,应该看到错误。
在生产中,我使用v.0.10.的东西,它仍然给出错误。同样,我认为这是有意为之,解决方案是在你的代码中处理错误。