本文由云+社区宣布
作者:草小灰
运用 Node.js 搭建 HTTP Server 已经是屡见不鲜的事。在临盆环境中,Node 历程腻滑重启直接关系到效劳的可靠性,它的重要性不容我们疏忽。既然是腻滑重启,就触及到新旧历程的代替过渡:
- 起首,保证新历程腻滑入场
- 其次,保证旧历程腻滑离场
本文重要议论下,在新旧历程代替过渡时期,如何保证旧历程腻滑离场。那如何的离场才算腻滑的呢?
如何定义腻滑离场
以历程离场作为时候支解点,我们能够把要求分为两类:增量要求
和存量要求
。
- 在历程离场前,住手吸收新的(
增量
)要求 - 在历程离场前,保证未完成的(
存量
)要求平常相应
所以,杀青以上两个目的,基本上我们就以为历程的离场是腻滑的。在谈如何做到历程腻滑离场前,我们须要一种机制,这类机制能让我们主动关照历程什么时候离场,这就触及到历程间通讯(IPC)的学问了,我们先简朴了解下。
历程间通讯
对 Unix 或类 Unix 体系而言,历程间通讯的体式格局有许多种 —— 信号(Signal)是个中的一种。
信号的品种有许多,如 SIGINT
、 SIGTERM
及 SIGKILL
等。这些信号视详细须要用于差别的场景,比方 SIGKILL
平常用于强杀历程。
我们能够在敕令行实行 kill -l
检察一切的信号,以下所示(个中的数字示意 signal number
):
$ kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGABRT 7) SIGEMT 8) SIGFPE
9) SIGKILL 10) SIGBUS 11) SIGSEGV 12) SIGSYS
13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGURG
17) SIGSTOP 18) SIGTSTP 19) SIGCONT 20) SIGCHLD
21) SIGTTIN 22) SIGTTOU 23) SIGIO 24) SIGXCPU
25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH
29) SIGINFO 30) SIGUSR1 31) SIGUSR2
我们能够运用 kill
敕令向历程发送指定信号:
# 发送 SIGTERM 信号(默许,不必指定信号范例)给历程
$ kill <pid>
# 发送 SIGINT 信号给历程,个中 <pid> 为详细的历程 ID
$ kill -INT <pid>
# 发送 SIGKILL 信号给历程
$ kill -KILL <pid>
# 或许
$ kill -9 <pid>
历程能够对吸收到的信号作出回应。对 Node 运用而言,信号是被看成事宜发送给 Node 历程的,历程吸收到 SIGTERM
及 SIGINT
事宜有默许回调,官方文档是这么形貌的:
‘SIGTERM’ and ‘SIGINT’ have default handlers on non-Windows platforms that reset the terminal mode before exiting with code 128 + signal number. If one of these signals has a listener installed, its default behavior will be removed (Node.js will no longer exit).
这句话写的很笼统,它是什么意思呢?我们以一个简朴的 Node 运用为例。
新建文件,键入以下代码,将其保存为 server.js
:
const http = require('http');
const server = http.createServer((req, res) => {
setTimeout(() => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('It works');
}, 5000);
});
server.listen(9420);
这里为了轻易测试,对运用吸收到的每一个 http 要求,守候 5 秒后再举行相应。
实行 node server.js
启动运用。为了给运用发送信号,我们须要猎取运用的历程 ID,我们能够运用 lsof
敕令检察:
$ lsof -i TCP:9420
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 70826 myunlessor 13u IPv6 0xd250033eef8912eb 0t0 TCP *:9420 (LISTEN)
事实上,我们也能够在代码里经由过程
console.log(process.pid)
猎取历程 ID。这里只是趁便引见一种,在晓得监听 TCP 端口的状况猎取历程的体式格局。
随后,我们提议一个要求,在收到相应之前(有 5 秒守候时候),我们给运用发送 SIGINT
信号。
$ curl http://localhost:9420 &
$ kill -INT 70826
curl: (52) Empty reply from server
[1]+ Exit 52 curl http://localhost:9420
能够看到,要求没能平常收到相应。也就是说,默许状况下,Node 运用在吸收到 SIGINT
信号时,会立时把历程杀死,疏忽历程还没处置惩罚完成的要求。所幸的是,我们能够手动监听历程的 SIGINT
事宜,像如许:
process.on('SIGINT', () => {
// do something here
});
假如我们在事宜回调里什么都不做,就意味着疏忽该信号,历程该干吗干吗,像什么事情都没发作一样。
那末,假如我手动监听 SIGKILL
会如何呢?对不起,SIGKILL
是不能被监听的,官方文档如是说:
‘SIGKILL’ cannot have a listener installed, it will unconditionally terminate Node.js on all platforms.
这是通情达理的,要晓得 SIGKILL
是用于强杀历程的,你没法干涉干与它的行动。
回到上面的题目,我们能够近似地理解为 Node 运用相应 SIGINT
事宜的默许回调是如许子的:
process.on('SIGINT', () => {
process.exit(128 + 2/* signal number */);
});
我们能够打印 exit code
来考证:
$ node server.js
$ echo $?
130
有了信号,我们就可以主动关照历程什么时候离场了,下面谈一谈历程如何腻滑离场。
如何让历程腻滑离场
我们在上面示例基础上,也就是在文件 server.js
中,补充以下代码:
process.on('SIGINT', () => {
server.close(err => {
process.exit(err ? 1 : 0);
});
});
这段代码很简朴,我们改写运用吸收到 SIGINT
事宜的默许行动,不再简朴粗犷直接杀死历程,而是在 server.close
要领回调中再挪用 process.exit
要领,接着继承实验一下。
$ lsof -i TCP:9420
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 75842 myunlessor 13u IPv6 0xd250033ec7c9362b 0t0 TCP *:9420 (LISTEN)
$ curl http://localhost:9420 &
[1] 75878
$ kill -2 75842
$ It works
[1]+ Done curl http://localhost:9420
能够看到,运用在退出前(即历程离场前),成功地相应了存量
要求。
我们还能够考证,历程离场前,确切不再吸收增量
要求:
$ curl http://127.0.0.1:9420
curl: (7) Failed to connect to 127.0.0.1 port 9420: Connection refused
这正是 server.close
所做的事,历程腻滑离场就是这么简朴,官方文档是这么形貌这个 API 的:
Stops the server from accepting new connections and keeps existing connections. This function is asynchronous, the server is finally closed when all connections are ended and the server emits a ‘close’ event. The optional callback will be called once the ‘close’ event occurs. Unlike that event, it will be called with an Error as its only argument if the server was not open when it was closed.
结束语
历程腻滑离场只是 Node 历程腻滑重启的一部分。临盆环境中,新旧历程的代替触及历程负载平衡、历程生命周期治理等各个方面的斟酌。专业的东西做专业的事,PM2 就是 Node 历程治理很好的挑选。
此文已由腾讯云+社区在各渠道宣布
猎取更多新颖手艺干货,能够关注我们腾讯云手艺社区-云加社区官方号及知乎机构号