我正在运行带有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__: …Run Code Online (Sandbox Code Playgroud) 我有一个多线程服务器(线程池),使用20个线程处理大量请求(一个节点最多500 /秒).有一个侦听器线程接受传入连接并将它们排队以供处理程序线程处理.一旦响应准备就绪,线程就会写出到客户端并关闭套接字.直到最近,一切似乎都很好,一个测试客户端程序在阅读响应后开始随机挂起.经过大量挖掘后,似乎服务器的close()实际上并没有断开套接字.我已经使用文件描述符编号为代码添加了一些调试打印,我得到了这种类型的输出.
Processing request for 21
Writing to 21
Closing 21
Run Code Online (Sandbox Code Playgroud)
close()的返回值为0,否则将打印另一个调试语句.在使用挂起的客户端输出此信息后,lsof将显示已建立的连接.
SERVER 8160 root 21u IPv4 32754237 TCP localhost:9980-> localhost:47530(ESTABLISHED)
客户端17747 root 12u IPv4 32754228 TCP localhost:47530-> localhost:9980(ESTABLISHED)
就像服务器永远不会将关闭序列发送到客户端一样,这种状态会一直挂起,直到客户端被终止,让服务器端处于关闭等待状态
SERVER 8160 root 21u IPv4 32754237 TCP localhost:9980-> localhost:47530(CLOSE_WAIT)
此外,如果客户端指定了超时,它将超时而不是挂起.我也可以手动运行
call close(21)
Run Code Online (Sandbox Code Playgroud)
在gdb的服务器中,客户端将断开连接.这可能发生在50,000个请求中,但可能不会在较长时间内发生.
Linux版本:2.6.21.7-2.fc8xen Centos版本:5.4(最终版)
套接字动作如下
服务器:
int client_socket; struct sockaddr_in client_addr; socklen_t client_len = sizeof(client_addr);
while(true) {
client_socket = accept(incoming_socket, (struct sockaddr *)&client_addr, &client_len);
if (client_socket == -1)
continue;
/* insert into queue here for threads to process */ …Run Code Online (Sandbox Code Playgroud)