簡體   English   中英

node.js服務器泄漏TCP連接?

[英]node.js server leaking TCP connections?

注意:請在帖子末尾看我的編輯。

我有一個node.js(Express)服務器,它服務大約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.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錯誤,但不能解決問題
  • 將響應超時(默認為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在提供這么多請求時應該沒有任何問題,所以我認為這是我的錯誤配置或者其他方面。 我做錯了什么? 謝謝!

PS:我從lsof的代碼/輸出中刪除了一堆內容,既存在隱私問題,也因為它與問題無關; 但是,如果需要任何其他信息,我會更新問題以盡快提供。

編輯:我想我找到了問題的根源。 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()

我懷疑這是解決問題的最優雅的方法,但它現在正常運作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM