优雅关闭节点表达不起作用

时间:2013-05-22 18:19:48

标签: node.js express coffeescript

我有一个简单的问题。我正在尝试关闭一个expressjs nodejs服务器,以便当前请求完成其响应并且新请求完全被拒绝。我已经将我的代码简单地用于简单的骨骼,以便更容易理解:

express = require("express")
http = require("http")
app = express()

app.configure ->
    app.set "port", process.env.PORT or 3000
    app.use app.router

ran = false
app.get '/testrun', (req, res)->
    console.log "received request"
    if ran
        res.json
            shouldnt: 'have gotten here'
    else
        ran = true
        setTimeout ->
            res.json
                response: 'fail!'
        , 8000
        console.log 'server closing'
        server.close()
        setTimeout ->
            process.exit()
        , 10000

server = http.createServer(app)
server.listen app.get("port"), ->
    console.log "Express server listening on port " + app.get("port")

基本上,我提出了两个请求。第一个需要8秒,服务器立即关闭。所以任何未来的请求都应该被拒绝。然而,第二个请求仍然可以通过。控制台输出:

$> Express server listening on port 3000
received request
server closing
received request

如果你能解释一下发生了什么,我会很感激。

更新:

Per Benjamin的回答,我尝试了他建议的测试代码,并且按预期工作。问题出在浏览器中。我编辑了原始服务器:

express = require("express")
http = require("http")
app = express()

app.configure ->
    app.set "port", process.env.PORT or 3000
    app.use app.router

ran = false
app.get '/testrun', (req, res)->
    console.log "received request"
    if ran
        res.json
            shouldnt: 'have gotten here'
    else
        ran = true
        setTimeout ->
            res.json
                response: 'fail!'
        , 5000
        console.log 'server closing' # changes here
        server.close ->
            console.log 'closed!'

server = http.createServer(app)
server.listen app.get("port"), ->
    console.log "Express server listening on port " + app.get("port")

请注意server.close周围的更改。当我运行Benjamin建议的测试代码时,你会得到预期的输出:

$>Express server listening on port 3000
received request
server closing
closed!

但是当我在chrome中打开两个标签时,请求第一个,等待几秒钟,然后请求第二个,我得到这个输出:

$>Express server listening on port 3000
received request
server closing
received request

如果没有process.exit,'封闭'回调永远不会被调用。一种奇怪的行为。

感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

express中的此函数.close()基于节点中http模块中的.close,它基于nodejs中net模块中的.close

让我们看看API的用途。

  

停止服务器接受新连接并保留现有连接。此功能是异步,当所有连接都结束且服务器发出“关闭”事件时,服务器最终会关闭。或者,您可以传递回调以侦听“关闭”事件。

这意味着你可能在同一个节点实例上运行测试代码而close没有机会运行。

此外,setTimeout不准确,可能会在80毫秒7980毫秒后触发8000毫秒的setTimeout。

当我运行以下代码以从不同的节点程序测试代码时:

http = require("http")
http.get "http://localhost:3000/testrun"
setTimeout http.get.bind(http,"http://localhost:3000/testrun"), 8000
setTimeout http.get.bind(http,"http://localhost:3000/testrun"), 9000

我得到了

$ coffee test.coffee
Express server listening on port 3000
received request
server closing

运行客户端的另一个窗口抛出ECONNREFUSED这是我期望的