亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Node.js 進程平滑離場剖析小結(jié)

 更新時間:2019年01月24日 15:01:50   作者:騰訊云加社區(qū)  
這篇文章主要介紹了Node.js 進程平滑離場剖析小結(jié),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

使用 Node.js 搭建 HTTP Server 已是司空見慣的事。在生產(chǎn)環(huán)境中,Node 進程平滑重啟直接關(guān)系到服務的可靠性,它的重要性不容我們忽視。既然是平滑重啟,就涉及到新舊進程的接替過渡:

  • 首先,保證新進程平滑入場
  • 其次,保證舊進程平滑離場

本文主要談論下,在新舊進程接替過渡期間,如何保證舊進程平滑離場。那怎樣的離場才算平滑的呢?

如何定義平滑離場

以進程離場作為時間分割點,我們可以把請求分為兩類:增量請求存量請求。

  • 在進程離場前,停止接收新的(增量)請求
  • 在進程離場前,保證未完成的(存量)請求正常響應

所以,達成以上兩個目標,基本上我們就認為進程的離場是平滑的。在談如何做到進程平滑離場前,我們需要一種機制,這種機制能讓我們主動通知進程何時離場,這就涉及到進程間通信(IPC)的知識了,我們先簡單了解下。

進程間通信

對 Unix 或類 Unix 系統(tǒng)而言,進程間通信的方式有很多種 —— 信號(Signal)是其中的一種。

信號的種類有很多,如 SIGINT、 SIGTERM SIGKILL 等。這些信號視具體需要用于不同的場景,比如 SIGKILL 一般用于強殺進程。

我們可以在命令行執(zhí)行 kill -l 查看所有的信號,如下所示(其中的數(shù)字表示 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 命令向進程發(fā)送指定信號:

# 發(fā)送 SIGTERM 信號(默認,無須指定信號類型)給進程
$ kill <pid>

# 發(fā)送 SIGINT 信號給進程,其中 <pid> 為具體的進程 ID
$ kill -INT <pid>

# 發(fā)送 SIGKILL 信號給進程
$ kill -KILL <pid>

# 或者
$ kill -9 <pid>

進程可以對接收到的信號作出回應。對 Node 應用而言,信號是被當作事件發(fā)送給 Node 進程的,進程接收到 SIGTERM 及 SIGINT 事件有默認回調(diào),官方文檔是這么描述的:

'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 秒后再進行響應。
執(zhí)行 node server.js 啟動應用。為了給應用發(fā)送信號,我們需要獲取應用的進程 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 端口的情況獲取進程的方式。

隨后,我們發(fā)起一個請求,在收到響應之前(有 5 秒等待時間),我們給應用發(fā)送 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
});

如果我們在事件回調(diào)里什么都不做,就意味著忽略該信號,進程該干嘛干嘛,像什么事情都沒發(fā)生一樣。

那么,如果 SIGKILL 會如何呢?對不起,SIGKILL 是不能的,官方文檔如是說:

'SIGKILL' cannot have a listener installed, it will unconditionally terminate Node.js on all platforms.

這是合情合理的,要知道 SIGKILL 是用于強殺進程的,你無法干預它的行為。

回到上面的問題,我們可以近似地理解為 Node 應用響應 SIGINT 事件的默認回調(diào)是這樣子的:

process.on('SIGINT', () => {
 process.exit(128 + 2/* signal number */);
});

我們可以打印 exit code 來驗證:

$ node server.js

$ echo $?
130

有了信號,我們就能主動通知進程何時離場了,下面談一談進程如何平滑離場。

如何讓進程平滑離場

我們在上面示例基礎(chǔ)上,也就是在文件 server.js 中,補充如下代碼:

process.on('SIGINT', () => {
 server.close(err => {
  process.exit(err ? 1 : 0);
 });
});

這段代碼很簡單,我們改寫應用接收到 SIGINT 事件的默認行為,不再簡單粗暴直接終止進程,而是在 server.close 方法回調(diào)中再調(diào)用 process.exit 方法,接著繼續(xù)試驗一下。

$ 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.

結(jié)束語

進程平滑離場只是 Node 進程平滑重啟的一部分。生產(chǎn)環(huán)境中,新舊進程的接替涉及進程負載均衡、進程生命周期管理等方方面面的考慮。專業(yè)的工具做專業(yè)的事,PM2 就是 Node 進程管理很好的選擇。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 使用Typescript和ES模塊發(fā)布Node模塊的方法

    使用Typescript和ES模塊發(fā)布Node模塊的方法

    這篇文章主要介紹了使用Typescript和ES模塊發(fā)布Node模塊的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-05-05
  • Node.js全局可用變量、函數(shù)和對象示例詳解

    Node.js全局可用變量、函數(shù)和對象示例詳解

    JavaScript中有一個特殊的對象,稱為全局對象(Global Object),它及其所有屬性都可以在程序的任何地方訪問,即全局變量,下面這篇文章主要給大家介紹了關(guān)于Node.js全局可用變量、函數(shù)和對象的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • 在node.js中讀寫文件的三種方法總結(jié)

    在node.js中讀寫文件的三種方法總結(jié)

    nodejs中所有與文件相關(guān)的操作都在fs模塊中,而讀寫操作又是我們會經(jīng)常用到的操作,nodejs的fs模塊針對讀操作為我們提供了readFile,read, createReadStream三個方法,接下來小編就和大家一起來分析一下這三種方法
    2023-09-09
  • express的中間件cookieParser詳解

    express的中間件cookieParser詳解

    這篇文章主要介紹了node.js中express的中間件cookieParser的使用方法,需要的朋友可以參考下
    2014-12-12
  • NodeJS 實現(xiàn)多語言的示例代碼

    NodeJS 實現(xiàn)多語言的示例代碼

    這篇文章主要介紹了NodeJS 實現(xiàn)多語言的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • 詳解nodejs 文本操作模塊-fs模塊(二)

    詳解nodejs 文本操作模塊-fs模塊(二)

    這篇文章主要介紹了詳解nodejs 文本操作模塊-fs模塊(二),主要包括文件的讀寫操作,有興趣的可以了解一下。
    2016-12-12
  • NodeJS實現(xiàn)微信公眾號關(guān)注后自動回復功能

    NodeJS實現(xiàn)微信公眾號關(guān)注后自動回復功能

    這篇文章主要為大家詳細介紹了NodeJS實現(xiàn)微信公眾號關(guān)注后自動回復功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • node.js操作mysql(增刪改查)

    node.js操作mysql(增刪改查)

    本文給大家分享的是使用node.js實現(xiàn)對mysql數(shù)據(jù)庫的增刪改查操作,有需要的小伙伴可以參考下,希望對大家學習node有所幫助。
    2015-07-07
  • NodeJS收發(fā)GET和POST請求的示例代碼

    NodeJS收發(fā)GET和POST請求的示例代碼

    本篇文章主要介紹了NodeJS收發(fā)GET和POST請求的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-08-08
  • Node.js中的HTTP?Server對象與GET、POST請求

    Node.js中的HTTP?Server對象與GET、POST請求

    這篇文章介紹了Node.js中的HTTP?Server對象與GET、POST請求,文中通過示例代碼介紹的非常詳細。對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-07-07

最新評論