node.JS HTTP 服务器的优雅关闭

问题描述 投票:0回答:4

这是我正在开发的一个简单的网络服务器

var server = require("http").createServer(function(req,resp) {
    resp.writeHead(200,{"Content-Type":"text/plain"})
    resp.write("hi")
    resp.end()
    server.close()
})
server.listen(80, 'localhost')
// The shortest webserver you ever did see! Thanks to Node.JS :)

除 keep-alive 外效果很好。当第一个请求进来时,

server.close
被调用。但是这个过程并没有结束。实际上 TCP 连接仍然打开,这允许另一个请求通过,这是我试图避免的。

如何关闭现有的保持连接?

http node.js exit
4个回答
23
投票

您可以控制连接的空闲超时,因此您可以设置保持活动连接将保持打开状态的时间。例如:

server=require('http').createServer(function(req,res) {
    //Respond
    if(req.url.match(/^\/end.*/)) {
        server.close();
        res.writeHead(200,{'Content-Type':'text/plain'});
        res.end('Closedown');
    } else {
        res.writeHead(200,{'Content-Type':'text/plain'});
        res.end('Hello World!');
    }
}).listen(1088);
//Set the idle timeout on any new connection
server.addListener("connection",function(stream) {
    stream.setTimeout(4000);
});

我们可以用netcat测试这个:

ben@quad-14:~/node$ echo -e "GET /test HTTP/1.1\nConnection: keep-alive\n\n" | netcat -C -q -1 localhost 1088
HTTP/1.1 200 OK
Content-Type: text/plain
Connection: keep-alive
Transfer-Encoding: chunked

c
Hello World!
0

after 4 seconds, the connection closes

现在我们可以证明关闭服务器是有效的:在所有空闲连接都被删除后,服务器退出:

ben@quad-14:~/node$ echo -e "GET /end HTTP/1.1\nConnection: keep-alive\n\n" | netcat -C -q -1 localhost 1088
HTTP/1.1 200 OK
Content-Type: text/plain
Connection: keep-alive
Transfer-Encoding: chunked

9
Closedown
0

after 4 seconds, the connection closes and the server exits


19
投票

可以在响应回调中调用

request.connection.destroy()
。这将关闭请求连接。

它也将结束你的过程,因为没有什么可做的,最终结果与在那里调用

process.exit()
相同。


4
投票

如果您关闭服务器作为正常关闭进程的一部分,您只需要:

var server = require('http').createServer(myFancyServerLogic);

server.on('connection', function (socket) {socket.unref();});
server.listen(80);

function myFancyServerLogic(req, res) {
    req.connection.ref();

    res.end('Hello World!', function () {
        req.connection.unref();
    });
}

基本上,您的服务器使用的套接字只会在它们实际为请求提供服务时使进程保持活动状态。当他们只是闲坐在那里(因为 Keep-Alive 连接)时,调用

server.close()
将关闭该进程,只要没有其他任何东西使该进程保持活动状态。如果你需要在服务器关闭后做其他事情,作为你的优雅关闭的一部分,你可以挂钩
process.on('beforeExit', callback)
来完成你的优雅关闭过程。


0
投票

如何关闭现有的保持连接?

您可以将服务器

keepAliveTimeout
属性设置为
0
(默认:
5000
,即5秒):

server.keepAliveTimeout

加入:v8.0.0

<number>
以毫秒为单位的超时。默认值:
5000
(5 秒)。

服务器在完成最后一个响应的写入之后,在销毁套接字之前需要等待额外传入数据的不活动毫秒数。如果服务器在保持活动超时触发之前收到新数据,它将重置常规不活动超时,即

server.timeout
.

0
的值将禁用传入连接的保持活动超时行为。
0
的值使 http 服务器的行为类似于 8.0.0 之前的 Node.js 版本,后者没有保持活动超时。

套接字超时逻辑是在连接上设置的,因此更改此值只会影响与服务器的新连接,而不影响任何现有连接。

或者,自 Node 18.2.0 起,您可以调用服务器

closeIdleConnections()
方法:

server.closeIdleConnections()

添加于:v18.2.0

关闭连接到此服务器的所有未发送请求或等待响应的连接。

例如,这对于 HTTP 服务器的单元测试非常有用:

import assert from 'node:assert/strict';
import http from 'node:http';
import test from 'node:test';

test.describe(() => {
  const server = http.createServer((request, response) => {
    response.statusCode = 200;
    response.setHeader('Content-Type', 'text/plain');
    response.setHeader('Content-Length', '12');
    response.end('hello, world');
  });
  server.listen(8000, 'localhost');

  test.after(() => {
    server.closeIdleConnections();
    server.close();
  });

  test.test(async () => {
    const response = await fetch('http://localhost:8000/');
    assert.equal(response.status, 200);
    assert.equal(response.headers.get('Content-Type'), 'text/plain');
    assert.equal(response.headers.get('Content-Length'), '12');
    assert.equal(await response.text(), 'hello, world');
  });
});

但是从Node 19.0.0开始,服务器

close()
方法隐式调用了服务器
closeIdleConnections()
方法,所以之前的建议不再适用:

server.close([callback])

历史

版本 变化
v19.0.0 该方法在返回之前关闭空闲连接。
v0.1.90 添加于:v0.1.90
  • 回调
    <Function>

停止服务器接受新连接并关闭连接到该服务器的所有未发送请求或等待响应的连接。见

net.Server.close()
.

© www.soinside.com 2019 - 2024. All rights reserved.