注意:请看帖子末尾的我的编辑。
我有一个node.js(Express)服务器,每秒服务大约15-30个请求。我正在提供一堆简单的JADE模板和一个Durandal SPA应用程序,其中大部分请求都是针对简单的JADE模板。一切都运行好几分钟,但服务器在一段时间后开始出现EMFILE错误并最终崩溃。稍作疑问后,我发现lsof -i -n -P | grep node
的输出在一段时间后包含了大量这类行:
node 8800 my_user 13u IPv4 906628 0t0 TCP 172.x.x.x:3000->x.x.x.x:44654 (ESTABLISHED)
node 8800 my_user 14u IPv4 908407 0t0 TCP 172.x.x.x:3000->x.x.x.x:13432 (ESTABLISHED)
node 8800 my_user 15u IPv4 908409 0t0 TCP 172.x.x.x:3000->x.x.x.x:38814 (ESTABLISHED)
node 8800 my_user 19u IPv4 906622 0t0 TCP 172.x.x.x:3000->x.x.x.x:56743 (ESTABLISHED)
node 8800 my_user 20u IPv4 907221 0t0 TCP 172.x.x.x:3000->x.x.x.x:46897 (ESTABLISHED)
...
我是node.js的初学者,但看起来它似乎无法解除已经完成的连接,最终导致EMFILE和崩溃。
我已经尝试了以下内容:
ulimit -n 2048
:这显然是一个临时解决方案,它会延迟EMFILE错误但不能解决问题在这两项调整到位的情况下,服务器需要更长时间才能崩溃,但最终仍然会这样做。即使没有任何负载,它似乎也无法处理"卡住" TCP ESTABLISHED连接,当请求再次开始到达时,打开的文件描述符数量不断增加,最终导致进程崩溃。
我的node.js服务器(在coffeescript中)看起来像这样(我使用mimosa来启动服务器,但我认为它不应该有任何区别):
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在提供这么多请求时不应该有任何问题,所以我认为这是我的错误配置或类似的事情。我做错了什么?谢谢!
P.S。:我从lsof
的代码/输出中删除了一堆内容,既出于隐私考虑,也因为它与问题无关;但是,如果需要任何其他信息,我会尽快更新问题以便提供。
编辑:我想我找到了问题的根源。 Express用于服务./my/template/n2
的连接确实在10秒后超时,但express.static
用于提供图像,css和其他静态资源的连接不是(它们是,但它们需要2 -5分钟发布他们的文件描述符...)。我想我的问题然后简化为:如何为express.static
提供的文件设置响应超时?我尝试在每个其他中间件之前使用app.use express.timeout(10000)
,但它似乎只适用于主JADE文件,而不适用于图像或CSS。
我正在使用Express 3.提前再次感谢您。
答案 0 :(得分:2)
在每隔一个app.use
调用之前添加此中间件后,问题就会解决:
app.use (req, res, next) ->
res.setTimeout(10000)
next()
我怀疑这是解决问题的最优雅方式,但它现在正常运作。