如何在node.js中中止http连接干净地closuresFD

我正在玩节点,并且(目前)只是试图通过HTTPstream式传输文件系统中的一些文件。

我的OS X Lion机器上的Apache Bench(ab)应用程序有问题,似乎过早地中断了连接。 这似乎突出了一个问题,我的node.js应用程序泄漏文件句柄,如果连接中止。

我已经减less了这个简单的node.jstesting用例。 当我启动它并运行“ab”时,由于打开文件句柄太多,我最终得到EMFILEexception:

// app.js var count = 0; require('http').createServer(function(req,res){ console.log('request ' + ++count); res.writeHead(200); require('fs').createReadStream( '/Users/tom/files/8339cdf73594d8f0aab87da123e9e0380723b471' ).pipe(res); }).listen('3000'); $ node app.js request 1 ... request 317 request 318 request 319 stream.js:105 throw er; // Unhandled stream error in pipe. ^ Error: EMFILE, too many open files '/Users/tom/files/8339cdf73594d8f0aab87da123e9e0380723b471' 

我假设发生的事情是HTTP连接被中止,但节点的.pipe()机制不知道停止从可读stream中读取并closuresFD,所以我试图处理HTTP ServerRequest上的'close'事件并销毁的FD,但似乎仍然从它读取,因为我得到一个错误的FD错误(EBADF),而不是:

 // app.js var count = 0; require('http').createServer(function(req,res){ console.log('request ' + ++count); res.writeHead(200); var file = require('fs').createReadStream( '/Users/tom/dev/cloudstore2/files/8339cdf73594d8f0aab87da123e9e0380723b471' ); req.on('close', function(){ console.log('request received close - destroying read FD'); file.destroy(); }); file.pipe(res); }).listen('3000'); $ node app.js ... request 112 request 113 request received close - destroying read FD request received close - destroying read FD request received close - destroying read FD request received close - destroying read FD request received close - destroying read FD request received close - destroying read FD request received close - destroying read FD events.js:48 throw arguments[1]; // Unhandled 'error' event ^ Error: EBADF, bad file descriptor 

是否有一个“正确”的方式来处理这些exception的HTTP连接,并closures了我的关联fs读取stream,或者我看到node.js的.pipe()处理中的错误?


更新:通过捕捉我的文件读取器上的“错误”事件,我可以避免在这个过程中死的应用程序,但是这是正确的方法吗? 我觉得我错过了一些方法来避免抛出一个错误的FD错误摆在首位。

 <snip> var file = require('fs').createReadStream( '/Users/tom/dev/cloudstore2/files/8339cdf73594d8f0aab87da123e9e0380723b471' ); file.on('error', function(err){ console.log('error handled in file reader: ' + err); }); req.on('close', function(){ console.log('request received close - destroying read FD'); file.destroy(); }); file.pipe(res); </snip> 

根据nodejs文档

http.ServerRequest

事件:'close'

表示在调用response.end()之前,下层连接已经终止或能够刷新。

就像'结束'一样,这个事件每个请求只发生一次,之后不再有'数据'事件触发。

注意:“closures”可以在“结束”之后触发,但反之亦然。

我认为end()会杀死你的pipe道的目标fh,这意味着如果end先被触发,那么有一个小窗口,在这个窗口里,pipe道在closures后可能试图写入请求fh。 尝试把你的file.destroy()调用放在end()事件中。

我试图testing我的想法,但我不能得到错误,所以请让我知道,如果这对你有效。 我很担心,当我将应用程序打开到其他用户时,会遇到这个问题。