NodeJS崩溃与多个请求

我的nodejs服务器实时地随机崩溃(并且总是在Web Stress Tool上使用10+线程请求)。 以下是我认为是根本原因的代码。

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个线程的压力testing时,详细的日志

 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) 

这是由src / unix / stream.c中的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; } 

我发现了这个问题的原因:

  1. stream->shutdown_reqint uv_shutdown(所以有人叫uv_shutdown ,谁叫uv_shutdown
  2. uv_shutdown不是一个简单的函数。 看到这里 。 这个函数的名字是StreamWrap::Shutdown
  3. StreamWrap::Shutdown用于nodejsSET_INSTANCE_METHOD("shutdown", StreamWrap::Shutdown, 0)shutdown方法是wrappers/pipe_wrapwrappers/tcp_wrap
  4. 所以有人从nodejs/lib调用shutdown 。 它可以是lib/netlib/tls
  5. 所以shutdown是从function onCryptoStreamFinishfunction onSocketFinish

所以你需要find谁在你的情况下发送关机请求。 onread ECANCELED意味着stream(例如socket1.pipe(socket2))已被终止。

顺便说一句我认为你可以解决你的问题,通过使用特殊的技术来销毁从lib / tlspipe道sockets:

 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(); }); });