在生产中运行我的Express应用程序时,我希望在其进程被终止时(即发送SIGTERM或SIGINT)正常关闭服务器.
这是我的代码的简化版本:
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个当前打开的连接”,直到我实际关闭浏览器窗口.即使关闭标签也会使连接保持打开状态.
因此,如果我按下Ctrl C来杀死我的服务器,它将进入超时并在10秒后打印“无法关闭连接”,同时继续打印“1个连接打开”.
解决方法
如果有人有兴趣,我自己找到了解决方案(很想听到评论中的反馈).
我为服务器上的连接添加了一个监听器,在数组中存储对这些连接的引用.关闭连接后,它们将从阵列中删除.
当服务器被终止时,通过调用其end方法来关闭每个连接.对于某些浏览器(例如Chrome),这还不够,所以在超时后,我会在每个连接上调用destroy.
const express = require('express'); const app = express(); app.get('/',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,10000); connections.forEach(curr => curr.end()); setTimeout(() => connections.forEach(curr => curr.destroy()),5000); }