繁体   English   中英

强制关闭 node.js http 服务器中的所有连接

[英]Force close all connections in a node.js http server

我有一个 http 服务器创建使用:

var server = http.createServer()

我想关闭服务器。 大概我会通过调用来做到这一点:

server.close()

但是,这只会阻止服务器接收任何新的 http 连接。 它不会关闭任何仍然打开的。 http.close()接受一个回调,并且在所有打开的连接实际断开之前不会执行该回调。 有没有办法强制关闭一切?

对我来说,问题的根源是我有 Mocha 测试,在他们的设置( beforeEach() )中启动一个 http 服务器,然后在他们的拆卸( afterEach() )中关闭它。 但由于仅调用server.close()不会完全关闭,后续的http.createServer()通常会导致EADDRINUSE错误。 等待close()完成也不是一种选择,因为打开的连接可能需要很长时间才能超时。

我需要一些方法来强制关闭连接。 我可以在客户端执行此操作,但会强制关闭所有测试连接,但我宁愿在服务器端执行此操作,即只告诉 http 服务器硬关闭所有 sockets。

你需要

  1. 订阅服务器的connection事件并将打开的套接字添加到数组
  2. 通过订阅他们的close事件并从阵列中删除已关闭的事件来跟踪打开的套接字
  3. 当您需要终止服务器时,在所有剩余的打开套接字上调用destroy

您还有机会在子进程中运行服务器并在需要时退出该进程。

对于那些偶然发现这个问题的人来说, https://github.com/isaacs/server-destroy库提供了一种简单的方法来destroy()服务器(使用Ege描述的方法)。

我通常使用类似的东西:

var express = require('express');
var server = express();

/* a dummy route */
server.get('/', function (req, res) {
    res.send('Hello World!');
});

/* handle SIGTERM and SIGINT (ctrl-c) nicely */
process.once('SIGTERM', end);
process.once('SIGINT', end);


var listener = server.listen(8000, function(err) {
    if (err) throw err;

    var host = listener.address().address;
    var port = listener.address().port;

    console.log('Server listening at http://%s:%s', host, port);
});


var lastSocketKey = 0;
var socketMap = {};
listener.on('connection', function(socket) {
    /* generate a new, unique socket-key */
    var socketKey = ++lastSocketKey;
    /* add socket when it is connected */
    socketMap[socketKey] = socket;
    socket.on('close', function() {
        /* remove socket when it is closed */
        delete socketMap[socketKey];
    });
});

function end() {
    /* loop through all sockets and destroy them */
    Object.keys(socketMap).forEach(function(socketKey){
        socketMap[socketKey].destroy();
    });

    /* after all the sockets are destroyed, we may close the server! */
    listener.close(function(err){
        if(err) throw err();

        console.log('Server stopped');
        /* exit gracefully */
        process.exit(0);
    });
}

就像EgeÖzcan所说,只需在连接事件上收集套接字,并在关闭服务器时将其销毁。

我用现代JS重写了原始答案:

const server1 = http.createServer(/*....*/);
const server1Sockets = new Set();

server1.on("connection", socket => {
    server1Sockets.add(socket);
    socket.on("close", () => {
        server1Sockets.delete(socket);
    });
});

function destroySockets(sockets) {
    for (const socket of sockets.values()) {
        socket.destroy();
    }
}

destroySockets(server1Sockets);

我的方法来自这个 ,它基本上是@EgeÖzcan所说的。

唯一的补充是我设置了一个关闭我的服务器的路由,因为节点没有从我的终端获取信号( 'SIGTERM''SIGINT' )。

好吧,节点在执行node whatever.js时从终端获取信号,但是当将该任务委托给脚本时(如package.json中的'start'脚本 - > npm start ),它无法通过Ctrl+C关闭Ctrl+C ,所以这种方法对我有用。

请注意我在Cygwin之下并且在此之前杀死服务器意味着关闭终端并再次重新打开它。

另请注意,我使用express表示路由。

var http=require('http');
var express= require('express');

var app= express();

app.get('/', function (req, res) {
    res.send('I am alive but if you want to kill me just go to <a href="/exit">/exit</a>');
});

app.get('/exit', killserver);

var server =http.createServer(app).listen(3000, function(){
  console.log('Express server listening on port 3000');
  /*console.log(process);*/
});


// Maintain a hash of all connected sockets
var sockets = {}, nextSocketId = 0;
server.on('connection', function (socket) {
  // Add a newly connected socket
  var socketId = nextSocketId++;
  sockets[socketId] = socket;
  console.log('socket', socketId, 'opened');

  // Remove the socket when it closes
  socket.on('close', function () {
    console.log('socket', socketId, 'closed');
    delete sockets[socketId];
  });

  // Extend socket lifetime for demo purposes
  socket.setTimeout(4000);
});


// close the server and destroy all the open sockets
function killserver() {
    console.log("U killed me but I'll take my revenge soon!!");
  // Close the server
  server.close(function () { console.log('Server closed!'); });
  // Destroy all open sockets
  for (var socketId in sockets) {
    console.log('socket', socketId, 'destroyed');
    sockets[socketId].destroy();
  }
};

v18.2.0 现在有一个closeAllConnections()方法

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM