1

我有一个简单的问题。我正在尝试关闭 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

如果您能解释发生了什么,我将不胜感激。

更新:

根据本杰明的回应,我尝试了他建议的测试代码,它按预期工作。问题出在浏览器上。我编辑了原始服务器:

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,“关闭”回调永远不会被调用。一种奇怪的行为。

谢谢你的帮助。

4

1 回答 1

2

express 中的此功能.close()基于.closenode 中的 http 模块,该模块基于 .closenodejs 中的 net 模块。

让我们看看 API 是怎么说的。

停止服务器接受新连接并保持现有连接。此函数是异步的,当所有连接结束并且服务器发出“关闭”事件时,服务器最终关闭。或者,您可以传递一个回调来监听“关闭”事件。

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

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

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

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这是我所期望的

于 2013-05-22T18:34:54.513 回答