如何立即关闭Node.js http(s)服务器?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何立即关闭Node.js http(s)服务器?相关的知识,希望对你有一定的参考价值。
我有一个包含http(s)服务器的Node.js应用程序。
在特定情况下,我需要以编程方式关闭此服务器。我目前正在做的是调用它的close()
函数,但这没有帮助,因为它等待任何保持活动的连接首先完成。
因此,基本上,这会关闭服务器,但仅在最短120秒的等待时间之后。但我希望服务器立即关闭 - 即使这意味着与当前处理的请求分手。
我不能做的是一个简单的
process.exit();
因为服务器只是应用程序的一部分,应用程序的其余部分应该保持运行。我正在寻找的是概念性的东西,如server.destroy();
或类似的东西。
我怎么能实现这个目标?
PS:通常需要连接的保持活动超时,因此减少此时间不是可行的选择。
诀窍是您需要订阅服务器的connection
事件,该事件为您提供新连接的套接字。你需要记住这个套接字,然后在调用server.close()
后直接使用socket.destroy()
销毁该套接字。
此外,您需要侦听套接字的close
事件,如果它自然离开,则将其从数组中删除,因为它的保持活动超时确实用完了。
我编写了一个小示例应用程序,您可以使用它来演示此行为:
// Create a new server on port 4000
var http = require('http');
var server = http.createServer(function (req, res) {
res.end('Hello world!');
}).listen(4000);
// 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);
});
// Count down from 10 seconds
(function countDown (counter) {
console.log(counter);
if (counter > 0)
return setTimeout(countDown, 1000, counter - 1);
// 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();
}
})(10);
基本上,它的作用是启动一个新的HTTP服务器,从10到0计数,并在10秒后关闭服务器。如果尚未建立连接,则服务器立即关闭。
如果已建立连接且仍处于打开状态,则会将其销毁。如果它已经自然死亡,那么此时只打印出一条消息。
我找到了一种方法来做到这一点,而无需跟踪连接或不得不强制关闭。我不确定它在Node版本中的可靠性如何,或者如果对此有任何负面影响,但它似乎对我正在做的事情完全正常。诀窍是在调用setImmediate
方法后立即使用close
发出“关闭”事件。这样工作如下:
server.close(callback);
setImmediate(function(){server.emit('close')});
至少对我来说,这最终会释放端口,这样我就可以在调用回调时启动一个新的HTTP(S)服务(这几乎是即时的)。现有连接保持开放。在更新Let的加密证书后,我正在使用它来自动重启HTTPS服务。
如果你需要在关闭服务器后保持进程存活,那么Golo Roden的解决方案可能是最好的。
但是,如果您正在关闭服务器作为正常关闭进程的一部分,那么您只需要:
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)
以完成正常的关闭过程。
https://github.com/isaacs/server-destroy库为destroy()
提供了一种简单的方法,使服务器具有问题所需的行为(通过跟踪打开的连接并在服务器销毁时销毁它们,如其他答案中所述)。
正如其他人所说,解决方案是跟踪所有打开的套接字并手动关闭它们。我的节点包killable可以为你做这个。一个例子(使用express,但你可以在任何http.server
实例上调用use killable):
var killable = require('killable');
var app = require('express')();
var server;
app.route('/', function (req, res, next) {
res.send('Server is going down NOW!');
server.kill(function () {
//the server is down when this is called. That won't take long.
});
});
var server = app.listen(8080);
killable(server);
还有另一个nodejs打包来执行关闭查杀连接:http-shutdown,在编写本文时(2016年9月)似乎合理维护并在NodeJS 6.x上为我工作
从文档中
用法
目前有两种方法可以使用这个库。第一个是显式包装Server对象:
// Create the http server
var server = require('http').createServer(function(req, res) {
res.end('Good job!');
});
// Wrap the server object with additional functionality.
// This should be done immediately after server construction, or before you start listening.
// Additional functionailiy needs to be added for http server events to properly shutdown.
server = require('http-shutdown')(server);
// Listen on a port and start taking requests.
server.listen(3000);
// Sometime later... shutdown the server.
server.shutdown(function() {
console.log('Everything is cleanly shutdown.');
});
第二个是隐式地将原型功能添加到Server对象:
// .extend adds a .withShutdown prototype method to the Server object
require('http-shutdown').extend();
var server = require('http').createServer(function(req, res) {
res.end('God job!');
}).withShutdown(); // <-- Easy to chain. Returns the Server object
// Sometime later, shutdown the server.
server.shutdown(function() {
console.log('Everything is cleanly shutdown.');
});
我最好的猜测是手动终止连接(即强行关闭它的套接字)。
理想情况下,这应该通过挖掘服务器的内部结构并手动关闭它的套接字来完成。或者,可以运行执行相同操作的shell命令(前提是服务器具有适当的权限和c。)
const Koa = require('koa')
const app = new Koa()
let keepAlive = true
app.use(async (ctx) => {
let url = ctx.request.url
// destroy socket
if (keepAlive === false) {
ctx.response.set('Connection', 'close')
}
switch (url) {
case '/restart':
ctx.body = 'success'
process.send('restart')
break;
default:
ctx.body = 'world-----' + Date.now()
}
})
const server = app.listen(9011)
process.on('message', (data, sendHandle) => {
if (data == 'stop') {
keepAlive = false
server.close();
}
})
process.exit(代码); //代码0代表成功,1代表失败
以上是关于如何立即关闭Node.js http(s)服务器?的主要内容,如果未能解决你的问题,请参考以下文章
带有自定义 Http(s) 代理和 Connect.js 中间件的 Node.js 代理