当我的进程被杀死时,如何优雅地关闭我的 Express 服务器? [英] How Do I Shut Down My Express Server Gracefully When Its Process Is Killed?

查看:34
本文介绍了当我的进程被杀死时,如何优雅地关闭我的 Express 服务器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在生产中运行我的 Express 应用程序时,我想在其进程被终止(即发送 SIGTERM 或 SIGINT)时优雅地关闭服务器.

When running my Express application in production, I want to shut down the server gracefully when its process is killed (i.e. a SIGTERM or SIGINT is sent).

这是我的代码的简化版本:

Here is a simplified version of my code:

const express = require('express');

const app = express();

app.get('/', (req, res) => res.json({ ping: true }));

const server = app.listen(3000, () => console.log('Running…'));

setInterval(() => server.getConnections(
    (err, connections) => console.log(`${connections} connections currently open`)
), 1000);

process.on('SIGTERM', shutDown);
process.on('SIGINT', shutDown);

function shutDown() {
    console.log('Received kill signal, shutting down gracefully');
    server.close(() => {
        console.log('Closed out remaining connections');
        process.exit(0);
    });

    setTimeout(() => {
        console.error('Could not close connections in time, forcefully shutting down');
        process.exit(1);
    }, 10000);
}

当我运行它并在浏览器中调用 URL http://localhost:3000/ 时,日志语句在 setInterval 函数中将继续打印1 个当前打开的连接",直到我真正关闭浏览器窗口.显然,即使关闭选项卡也会保持连接打开.

When I run it and call the URL http://localhost:3000/ in a browser, the log statement in the setInterval function will keep printing "1 connection currently open" until I actually close the browser window. Even closing the tab will keep the connection open, apparently.

所以我按 Ctrl+C 杀死我的服务器,它会遇到超时并在 10 秒后打印无法关闭连接",同时继续打印1 个连接打开".

So wenn I kill my server by hitting Ctrl+C, it will run into the timeout and print "Could not close connections" after 10 seconds, all the while continuing to print "1 connection open".

仅当我在终止进程之前关闭浏览器窗口时,我才会收到关闭剩余连接"消息.

Only if I close the browser window before killing the process I get the "closed out remaining connections" message.

我在这里遗漏了什么?正常关闭 Express 服务器的正确方法是什么?

推荐答案

如果有人感兴趣,我自己找到了一个解决方案(很想在评论中听到反馈).

In case anyone is interested, I found a solution myself (would love to hear feedback in comments).

我为在服务器上打开的连接添加了一个侦听器,将这些连接的引用存储在一个数组中.当连接关闭时,它们将从数组中删除.

I added a listener for connections opening on the server, storing references to those connections in an array. When the connections are closed, they are removed from the array.

当服务器被杀死时,每个连接都会通过调用它的 end 方法关闭.对于某些浏览器(例如 Chrome),这还不够,所以在超时后,我在每个连接上调用 destroy.

When the server is killed, each of the connection is closed by calling its end methods. For some browsers (e.g. Chrome), this is not enough, so after a timeout, I call destroy on each connection.

const express = require('express');

const app = express();

app.get('/', (req, res) => res.json({ ping: true }));

const server = app.listen(3000, () => console.log('Running…'));

setInterval(() => server.getConnections(
    (err, connections) => console.log(`${connections} connections currently open`)
), 1000);

process.on('SIGTERM', shutDown);
process.on('SIGINT', shutDown);

let connections = [];

server.on('connection', connection => {
    connections.push(connection);
    connection.on('close', () => connections = connections.filter(curr => curr !== connection));
});

function shutDown() {
    console.log('Received kill signal, shutting down gracefully');
    server.close(() => {
        console.log('Closed out remaining connections');
        process.exit(0);
    });

    setTimeout(() => {
        console.error('Could not close connections in time, forcefully shutting down');
        process.exit(1);
    }, 10000);

    connections.forEach(curr => curr.end());
    setTimeout(() => connections.forEach(curr => curr.destroy()), 5000);
}

这篇关于当我的进程被杀死时,如何优雅地关闭我的 Express 服务器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆