node.js服务器泄漏TCP连接?

注意:请参阅我在post末尾的修改。

我有一个node.js(快速)服务器,它服务大约15-30个请求/秒。 我提供了一些简单的JADE模板和一个Durandal SPA应用程序,大部分的请求都是为了简单的JADE模板。 一切都会好几分钟,但服务器开始在一段时间后得到EMFILE错误,最终崩溃。 排除故障后,我发现lsof -i -n -P | grep node的输出 一段时间后lsof -i -n -P | grep node包含了这么大量的行:

 node 8800 my_user 13u IPv4 906628 0t0 TCP 172.xxx:3000->xxxx:44654 (ESTABLISHED) node 8800 my_user 14u IPv4 908407 0t0 TCP 172.xxx:3000->xxxx:13432 (ESTABLISHED) node 8800 my_user 15u IPv4 908409 0t0 TCP 172.xxx:3000->xxxx:38814 (ESTABLISHED) node 8800 my_user 19u IPv4 906622 0t0 TCP 172.xxx:3000->xxxx:56743 (ESTABLISHED) node 8800 my_user 20u IPv4 907221 0t0 TCP 172.xxx:3000->xxxx:46897 (ESTABLISHED) ... 

我是一个初学node.js,但它看起来像无法解雇已经完成的连接,最终导致EMFILE和崩溃。

我已经尝试了以下内容:

  • ulimit -n 2048 :这显然是一个临时解决scheme,它延迟了EMFILE错误,但并没有解决问题
  • 降低响应超时(默认情况下是2分钟,如果我正确记得)接近5-10秒

在这两个调整的地方,服务器需要很长的时间才能崩溃,但最终还是这样。 即使没有任何负载,似乎也无法处理“卡住的”TCP ESTABLISHED连接,并且当请求开始再次到达时,打开的文件描述符的数量不断增长并最终导致进程崩溃。

我的node.js服务器(在coffeescript中)看起来像这样(我使用含羞草启动服务器,但我不认为这应该有所作为):

 express = require 'express' engines = require 'consolidate' fs = require 'fs' http = require 'http' https = require 'https' options = ca: fs.readFileSync __dirname + '/ssl/ca.pem' key: fs.readFileSync __dirname + '/ssl/key.pem' cert: fs.readFileSync __dirname + '/ssl/cert.pem' exports.startServer = (config, callback) -> app = express() app.configure -> app.set 'port', config.server.port app.set 'views', config.server.views.path app.engine config.server.views.extension, engines[config.server.views.compileWith] app.set 'view engine', config.server.views.extension app.use express.logger({ format: ":date :method :remote-addr :url :response-time" }) app.use express.favicon __dirname + '/public/favicon.ico' app.use express.bodyParser() app.use express.methodOverride() app.use express.compress() app.use express.static(config.watch.compiledDir) app.use config.server.base, app.router app.configure 'development', -> app.use express.errorHandler() app.get '/my/route/n1', (req, res) -> res.render "./my/template/n1" app.get '/my/route/n2', (req, res) -> # route getting the bulk of requests res.setTimeout(10000) # timeout introducted attempting to fix the problem res.render "./my/template/n2" app.get '/my/route/n3', (req, res) -> res.render "./my/template/n3" app.get '*/?', (req, res) -> res.render 'index' server = https.createServer options, app server.listen config.server.port, -> console.log "Express server listening on port %d in %s mode", server.address().port, app.settings.env callback server 

我认为node.js不应该有任何问题提供这个数量的请求,所以我认为这是我的一个错误的configuration或沿着这些线的东西。 我做错了什么? 谢谢!

PS:我从lsof的代码/输出中为隐私问题编辑了一堆东西,也是因为这个问题应该是无关紧要的。 但是,如果需要其他信息,我会更新问题,尽快提供。

编辑:我想我find了我的问题的来源。 Express用于服务./my/template/n2的连接确实在10秒后超时,但是express.static用于连接图像,css和其他静态资源的连接不是(它们是,但是它们需要2 -5分钟释放他们的文件描述符…)。 我想我的问题然后简化为:如何设置由express.static服务的文件的响应超时? 我尝试过在每个其他中间件之前使用app.use express.timeout(10000) ,但它似乎只适用于主JADE文件,而不适用于图像或CSS。

我正在使用Express 3.提前再次感谢您。

在每隔一个app.use调用之前添加这个中间件后,问题就会解决:

  app.use (req, res, next) -> res.setTimeout(10000) next() 

我怀疑这是解决问题的最优雅的方式,但现在工作正常。