我的nodejs服务器实时随机崩溃(并且总是在具有10+线程请求的Web压力工具上)。以下是我认为是根本原因的代码。
main.js
--------
app = express():
---------
app.get('/image/*', actions.download);
actions.js
var request = require('request');
exports.download = function(req, res){
var url = <Amazon s3 URL>;
req.pipe(request(url)).pipe(res);
};
当服务器崩溃时,我在nohup中遇到错误
stream.js:94
throw er; // Unhandled stream error in pipe.
^
Error: socket hang up
at createHangUpError (http.js:1476:15)
at Socket.socketOnEnd [as onend] (http.js:1572:23)
at Socket.g (events.js:180:16)
at Socket.emit (events.js:117:20)
at _stream_readable.js:943:16
at process._tickCallback (node.js:419:13)
我尝试使用sudo NODE_DEBUG=net node main.js
并使用10个线程进行压力测试时的详细日志
NET: 3017 Socket._read readStart
NET: 3017 afterWrite 0 { domain: null, bytes: 335, oncomplete: [Function: afterWrite] }
NET: 3017 afterWrite call cb
NET: 3017 onread ECANCELED 164640 4092 168732
NET: 2983 got data
NET: 2983 onSocketFinish
NET: 2983 oSF: not ended, call shutdown()
NET: 2983 destroy undefined
NET: 2983 destroy
NET: 2983 close
NET: 2983 close handle
Error: read ECONNRESET
at errnoException (net.js:904:11)
at TCP.onread (net.js:558:19)
答案 0 :(得分:0)
这是libuv
if (stream->shutdown_req) {
/* The UV_ECANCELED error code is a lie, the shutdown(2) syscall is a
* fait accompli at this point. Maybe we should revisit this in v0.11.
* A possible reason for leaving it unchanged is that it informs the
* callee that the handle has been destroyed.
*/
uv__req_unregister(stream->loop, stream->shutdown_req);
uv__set_artificial_error(stream->loop, UV_ECANCELED);
stream->shutdown_req->cb(stream->shutdown_req, -1);
stream->shutdown_req = NULL;
}
中的stream->shutdown_req
。我们在这里:
int uv_shutdown(
我找到了这个问题的原因:
uv_shutdown
由uv_shutdown
分配。所以有人打电话给uv_shutdown
。谁致电StreamWrap::Shutdown
?StreamWrap::Shutdown
不是一个简单的功能。见src/unix/stream.c。此函数的名称为nodejs
。SET_INSTANCE_METHOD("shutdown", StreamWrap::Shutdown, 0)
用于shutdown
:wrappers/pipe_wrap
。 wrappers/tcp_wrap
方法是shutdown
和nodejs/lib
lib/net
致电lib/tls
。它可以是shutdown
和function onCryptoStreamFinish
。function onSocketFinish
或onread ECANCELED
会调用pair.encrypted.on('close', function() {
process.nextTick(function() {
// Encrypted should be unpiped from socket to prevent possible
// write after destroy.
pair.encrypted.unpipe(socket);
socket.destroy();
});
});
。所以你需要找到谁在你的情况下发送了关机请求。 {{1}}表示流已被杀死(例如socket1.pipe(socket2))。
BTW我认为您可以通过使用特殊技术来解决您的问题,以便从here销毁管道套接字:
{{1}}