最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

  • 首先,保證新進(jìn)程平滑入場
  • 其次,保證舊進(jìn)程平滑離場

本文主要談?wù)撓拢谛屡f進(jìn)程接替過渡期間,如何保證舊進(jìn)程平滑離場。那怎樣的離場才算平滑的呢?

如何定義平滑離場

以進(jìn)程離場作為時(shí)間分割點(diǎn),我們可以把請求分為兩類:增量請求存量請求。

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

所以,達(dá)成以上兩個(gè)目標(biāo),基本上我們就認(rèn)為進(jìn)程的離場是平滑的。在談如何做到進(jìn)程平滑離場前,我們需要一種機(jī)制,這種機(jī)制能讓我們主動(dòng)通知進(jìn)程何時(shí)離場,這就涉及到進(jìn)程間通信(IPC)的知識(shí)了,我們先簡單了解下。

進(jìn)程間通信

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

信號(hào)的種類有很多,如 SIGINT、 SIGTERM SIGKILL 等。這些信號(hào)視具體需要用于不同的場景,比如 SIGKILL 一般用于強(qiáng)殺進(jìn)程。

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

# 發(fā)送 SIGTERM 信號(hào)(默認(rèn),無須指定信號(hào)類型)給進(jìn)程
$ kill <pid>

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

# 發(fā)送 SIGKILL 信號(hào)給進(jìn)程
$ kill -KILL <pid>

# 或者
$ kill -9 <pid>

進(jìn)程可以對接收到的信號(hào)作出回應(yīng)。對 Node 應(yīng)用而言,信號(hào)是被當(dāng)作事件發(fā)送給 Node 進(jìn)程的,進(jìn)程接收到 SIGTERM 及 SIGINT 事件有默認(rèn)回調(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).

這句話寫的很抽象,它是什么意思呢?我們以一個(gè)簡單的 Node 應(yīng)用為例。

新建文件,鍵入如下代碼,將其保存為 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);

這里為了方便測試,對應(yīng)用接收到的每個(gè) http 請求,等待 5 秒后再進(jìn)行響應(yīng)。
執(zhí)行 node server.js 啟動(dòng)應(yīng)用。為了給應(yīng)用發(fā)送信號(hào),我們需要獲取應(yīng)用的進(jìn)程 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)

事實(shí)上,我們也可以在代碼里通過 console.log(process.pid) 獲取進(jìn)程 ID。這里只是順便介紹一種,在知道 TCP 端口的情況獲取進(jìn)程的方式。

隨后,我們發(fā)起一個(gè)請求,在收到響應(yīng)之前(有 5 秒等待時(shí)間),我們給應(yīng)用發(fā)送 SIGINT 信號(hào)。

$ curl http://localhost:9420 &

$ kill -INT 70826
curl: (52) Empty reply from server
[1]+ Exit 52         curl http://localhost:9420

可以看到,請求沒能正常收到響應(yīng)。也就是說,默認(rèn)情況下,Node 應(yīng)用在接收到 SIGINT 信號(hào)時(shí),會(huì)馬上把進(jìn)程終止,無視進(jìn)程還沒處理完成的請求。所幸的是,我們可以手動(dòng)進(jìn)程的 SIGINT 事件,像這樣:

process.on('SIGINT', () => {
 // do something here
});

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

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

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

這是合情合理的,要知道 SIGKILL 是用于強(qiáng)殺進(jìn)程的,你無法干預(yù)它的行為。

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

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

我們可以打印 exit code 來驗(yàn)證:

$ node server.js

$ echo $?
130

有了信號(hào),我們就能主動(dòng)通知進(jìn)程何時(shí)離場了,下面談一談進(jìn)程如何平滑離場。

如何讓進(jìn)程平滑離場

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

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

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

$ 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

可以看到,應(yīng)用在退出前(即進(jìn)程離場前),成功地響應(yīng)了存量請求。

我們還可以驗(yàn)證,進(jìn)程離場前,確實(shí)不再接收增量請求:

$ curl http://127.0.0.1:9420
curl: (7) Failed to connect to 127.0.0.1 port 9420: Connection refused

這正是 server.close 所做的事,進(jìn)程平滑離場就是這么簡單,官方文檔是這么描述這個(gè) 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é)束語

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

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

相關(guān)文章

  • node環(huán)境下運(yùn)行js代碼缺少window環(huán)境的原因以及解決方法

    node環(huán)境下運(yùn)行js代碼缺少window環(huán)境的原因以及解決方法

    Node是一個(gè)基于Chrome?V8引擎的運(yùn)行環(huán)境,讓JavaScript運(yùn)行在服務(wù)端的開發(fā)平臺(tái),這篇文章主要給大家介紹了關(guān)于node環(huán)境下運(yùn)行js代碼缺少window環(huán)境的原因以及解決方法,需要的朋友可以參考下
    2023-11-11
  • 新手必須知的Node.js 4個(gè)JavaScript基本概念

    新手必須知的Node.js 4個(gè)JavaScript基本概念

    本文介紹了4個(gè)基本JavaScript概念,它是你學(xué)習(xí)node.js所必需要掌握,下面就讓我們來看一下具體是哪4個(gè)基本JavaScript概念
    2018-09-09
  • 使用NVM下載Node.js管理多版本的詳細(xì)教程(附圖文)

    使用NVM下載Node.js管理多版本的詳細(xì)教程(附圖文)

    在開發(fā)過程會(huì)一直遇到nodejs的版本問題,直接安裝則只有一個(gè)版本,極其不方便,nvm則是用來管理nodejs的工具,可以通過nvm來安裝切換不同版本的nodejs,所以本文給大家介紹了使用NVM下載Node.js管理多版本的詳細(xì)教程,文中有詳細(xì)的圖文教程,需要的朋友可以參考下
    2025-04-04
  • 詳解如何實(shí)現(xiàn)一個(gè)簡單的Node.js腳手架

    詳解如何實(shí)現(xiàn)一個(gè)簡單的Node.js腳手架

    本篇文章主要介紹了如何實(shí)現(xiàn)一個(gè)簡單的Node.js腳手架,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-12-12
  • 淺析Node.js:DNS模塊的使用

    淺析Node.js:DNS模塊的使用

    本篇文章主要介紹了Node.js:DNS模塊的使用,DNS模塊包涵有關(guān)DNS查詢和操作的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2016-11-11
  • nodejs前端模板引擎swig入門詳解

    nodejs前端模板引擎swig入門詳解

    這篇文章主要介紹了nodejs前端模板引擎swig入門詳解,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-05-05
  • Docker平臺(tái)下NodeJs?Puppeteer實(shí)現(xiàn)html轉(zhuǎn)pdf過程示例

    Docker平臺(tái)下NodeJs?Puppeteer實(shí)現(xiàn)html轉(zhuǎn)pdf過程示例

    這篇文章主要為大家介紹了Docker平臺(tái)下NodeJs?Puppeteer實(shí)現(xiàn)html轉(zhuǎn)pdf過程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • node.js 開發(fā)指南 – Node.js 連接 MySQL 并進(jìn)行數(shù)據(jù)庫操作

    node.js 開發(fā)指南 – Node.js 連接 MySQL 并進(jìn)行數(shù)據(jù)庫操作

    通常在NodeJS開發(fā)中我們經(jīng)常涉及到操作數(shù)據(jù)庫,尤其是 MySQL ,作為應(yīng)用最為廣泛的開源數(shù)據(jù)庫則成為我們的首選,本篇就來介紹下如何通過NodeJS來操作 MySQL 數(shù)據(jù)庫。
    2014-07-07
  • Node.js對MongoDB數(shù)據(jù)庫實(shí)現(xiàn)模糊查詢的方法

    Node.js對MongoDB數(shù)據(jù)庫實(shí)現(xiàn)模糊查詢的方法

    模糊查詢是數(shù)據(jù)庫的基本操作之一,下面這篇文章主要給大家介紹了利用Node.js對MongoDB數(shù)據(jù)庫實(shí)現(xiàn)模糊查詢的方法教程,文中給出了詳細(xì)的介紹和示例代碼,對大家具有一定的參考價(jià)值,需要的朋友們下面來一起看看吧。
    2017-05-05
  • node-sass@4.14.1報(bào)錯(cuò)的最終解決方案分享

    node-sass@4.14.1報(bào)錯(cuò)的最終解決方案分享

    最近在安裝node-sass@4.14.1的時(shí)候遇到了些問題,所以下面這篇文章主要給大家介紹了關(guān)于node-sass@4.14.1報(bào)錯(cuò)的最終解決方案,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-09-09

最新評論

满城县| 石泉县| 罗田县| 秭归县| 永济市| 义马市| 开远市| 洮南市| 政和县| 布拖县| 阿拉善左旗| 海口市| 罗城| 炉霍县| 杭锦旗| 杭锦后旗| 枞阳县| 林甸县| 武穴市| 洪泽县| 大名县| 彭阳县| 荥经县| 玉溪市| 吴川市| 青川县| 嘉祥县| 如东县| 都安| 邵阳市| 荔浦县| 万源市| 澄江县| 新巴尔虎右旗| 临夏县| 罗定市| 桃园县| 和平县| 类乌齐县| 崇州市| 固原市|