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

深入理解Node.js中的進(jìn)程管理

 更新時(shí)間:2017年03月13日 10:39:45   作者:黃騰飛  
這篇文章主要介紹了Node.js中進(jìn)程管理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),相信對(duì)大家的學(xué)習(xí)或者工作具有一定的參考價(jià)值,需要的朋友們下面來一起看看吧。

前言

本文主要對(duì) Node.js 中進(jìn)程管理相關(guān)的東西做一個(gè)簡單介紹,包括 process 對(duì)象、child_process 模塊cluster 模塊,詳細(xì)的 API 可以查看官方文檔,下面來看看詳細(xì)的介紹吧。

Process 對(duì)象

process 是 Node.js 的一個(gè)全局對(duì)象,可以在任何地方直接使用而不需要 require 命令加載。process 對(duì)象提供了 當(dāng)前 node 進(jìn)程 的命令行參數(shù)、標(biāo)準(zhǔn)輸入輸出、運(yùn)行環(huán)境和運(yùn)行狀態(tài)等信息。

常用屬性

argv

process.argv 屬性返回一個(gè)數(shù)組,第一個(gè)元素是 node,第二個(gè)元素是腳本文件名稱,其余成員是腳本文件的參數(shù)。

$ node process-2.js one two=three four

0: /usr/local/bin/node
1: /Users/mjr/work/node/process-2.js
2: one
3: two=three
4: four

env

process.env 返回一個(gè)對(duì)象,包含了當(dāng)前 Shell 的所有環(huán)境變量,比如:

{
 TERM: 'xterm-256color',
 SHELL: '/bin/zsh',
 USER: 'huangtengfei',
 PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin',
 PWD: '/Users/huangtengfei',
 HOME: '/Users/huangtengfei'
}

這個(gè)屬性通常的使用場景是,新建一個(gè) NODE_ENV 變量,用來確定當(dāng)前所處的開發(fā)階段,生成階段設(shè)為 production,開發(fā)階段設(shè)為 develop ,然后在腳本中讀取 process.env.NODE_ENV 再做相應(yīng)處理即可。

運(yùn)行腳本時(shí)可以這樣改變環(huán)境變量:

$ export NODE_ENV=production && node app.js
# 或者
$ NODE_ENV=production node app.js

stdin/stdout

process.stdin 指向標(biāo)準(zhǔn)輸入(鍵盤到緩沖區(qū)里的東西),返回一個(gè)可讀的流:

process.stdin.setEncoding('utf8');

process.stdin.on('readable', () => {
 var chunk = process.stdin.read();
 if (chunk !== null) {
 process.stdout.write(`data: ${chunk}`);
 }
});

process.stdin.on('end', () => {
 process.stdout.write('end');
});

process.stdout 指向標(biāo)準(zhǔn)輸出(向用戶顯示內(nèi)容),返回一個(gè)可寫的流:

const fs = require('fs');

fs.createReadStream('wow.txt')
 .pipe(process.stdout);

常用方法

cwd()

process.cwd() 返回運(yùn)行 Node 的工作目錄(絕對(duì)路徑),比如在目錄 /Users/huangtengfei/abc 下執(zhí)行 node server.js,那么 process.cwd() 返回的就是 /Users/huangtengfei/abc。

另一個(gè)常用的獲取路徑的方法是 __dirname,它返回的是執(zhí)行文件時(shí)該文件在文件系統(tǒng)中所在的目錄。注意 process.cwd() __dirname 的不同,前者是進(jìn)程發(fā)起時(shí)的位置,后者是腳本的位置,兩者可能不一致。

on()

process 對(duì)象部署了 EventEmitter 接口,可以使用 process.on() 方法監(jiān)聽各種事件,并指定回調(diào)函數(shù)。比如監(jiān)聽到系統(tǒng)發(fā)出進(jìn)程終止信號(hào)時(shí)關(guān)閉服務(wù)器然后退出進(jìn)程:

process.on('SIGTERM', function () {
 server.close(function () {
 process.exit(0);
 });
});

exit()

process.exit() 會(huì)讓 Node 立即終止當(dāng)前進(jìn)程(同步),參數(shù)為一個(gè)退出狀態(tài)碼,0 表示成功,大于 0 的任意整數(shù)表示失敗。

kill()

process.kill() 用來對(duì)特定 id 的進(jìn)程(process.pid)發(fā)送信號(hào),默認(rèn)為 SIGINT 信號(hào)。比如殺死當(dāng)前進(jìn)程:

process.kill(process.pid, 'SIGTERM');

雖然名字叫 kill ,但其實(shí) process.kill() 只是負(fù)責(zé)發(fā)送信號(hào),具體發(fā)送完信號(hào)之后這個(gè)怎么處理這個(gè)指定進(jìn)程,取決于信號(hào)種類和接收到這個(gè)信號(hào)之后做了什么操作(比如 process.exit() 或者只是 console.log('Ignored this single'))。

Child Process 模塊

child_process 模塊用于創(chuàng)建和控制子進(jìn)程,其中最核心的是 .spawn() ,其他 API 算是針對(duì)特定場景對(duì)它的封裝。使用前要先 require 進(jìn)來:

const cp = require('child_process');

exec(command[, options][, callback])

exec() 方法用于執(zhí)行 shell 命令,它的第一個(gè)參數(shù)是字符串形式的命令,第二個(gè)參數(shù)(可選)用來指定子進(jìn)程運(yùn)行時(shí)的定制化操作,第三個(gè)參數(shù)(可選)用來設(shè)置執(zhí)行完命令的回調(diào)函數(shù)。比如在一個(gè)特定目錄 /Users/huangtengfei/abc 下執(zhí)行 ls -l 命令:

cp.exec('ls -l', {
 cwd: '/Users/huangtengfei/abc'
}, (error, stdout, stderr) => {
 if (error) {
 console.error(`exec error: ${error}`);
 return;
 }
 console.log(`stdout: ${stdout}`);
 console.log(`stderr: ${stderr}`);
})

spawn(command[, args][, options])

spawn() 用來創(chuàng)建一個(gè)子進(jìn)程執(zhí)行特定命令,與 exec() 的區(qū)別是它沒有回調(diào)函數(shù),只能通過監(jiān)聽事件來獲取運(yùn)行結(jié)果,它適用于子進(jìn)程長時(shí)間運(yùn)行的情況,可以實(shí)時(shí)輸出結(jié)果。

const ls = cp.spawn('ls', ['-l']);

ls.stdout.on('data', (data) => {
 console.log(`stdout: ${data}`);
});

ls.stderr.on('data', (data) => {
 console.log(`stderr: ${data}`);
});

ls.on('close', (code) => {
 console.log(`child process exited with code $[code]`);
});

使用 spawn 可以實(shí)現(xiàn)一個(gè)簡單的守護(hù)進(jìn)程,在工作進(jìn)程不正常退出時(shí)重啟工作進(jìn)程:

/* daemon.js */
function spawn(mainModule) {
 const worker = cp.spawn('node', [ mainModule ]);

 worker.on('exit', function (code) {
  if (code !== 0) {
   spawn(mainModule);
  }
 });
}

spawn('worker.js');

fork(modulePath[, args][, options])

fork() 用來創(chuàng)建一個(gè)子進(jìn)程執(zhí)行 node 腳本,fork('./child.js') 相當(dāng)于 spawn('node', ['./child.js']) , 區(qū)別在于 fork 會(huì)在父子進(jìn)程之間建立一個(gè)通信管道(fork() 的返回值),用于進(jìn)程間通信。對(duì)該通信管道對(duì)象可以監(jiān)聽 message 事件,用來獲取子進(jìn)程返回的信息,也可以向子進(jìn)程發(fā)送信息。

/* main.js */
const proc = cp.fork('./child.js');
proc.on('message', function(msg) {
 console.log(`parent got message: ${msg}`);
});
proc.send({ hello: 'world' });

/* child.js */
process.on('message', function(msg) {
 console.log(`child got message: ${msg}`);
});
process.send({ foo: 'bar' });

Cluster 模塊

Node.js 默認(rèn)單進(jìn)程執(zhí)行,但這樣就無法利用多核計(jì)算機(jī)的資源,cluster 模塊的出現(xiàn)就是為了解決這個(gè)問題的。在開發(fā)服務(wù)器程序時(shí),可以通過 cluster 創(chuàng)建一個(gè)主進(jìn)程和多個(gè) worker 進(jìn)程,讓每個(gè) worker 進(jìn)程運(yùn)行在一個(gè)核上,統(tǒng)一通過主進(jìn)程監(jiān)聽端口和分發(fā)請(qǐng)求。

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
 console.log(`Master ${process.pid} is running`);

 // Fork workers.
 for (let i = 0; i < numCPUs; i++) {
 cluster.fork();
 }

 cluster.on('exit', (worker, code, signal) => {
 console.log(`worker ${worker.process.pid} died`);
 });
} else {
 // Workers can share any TCP connection
 // In this case it is an HTTP server
 http.createServer((req, res) => {
 res.writeHead(200);
 res.end('hello world\n');
 }).listen(8000);

 console.log(`Worker ${process.pid} started`);
}

常用屬性和方法

isMaster/isWorker

cluster.isMaster 用來判斷當(dāng)前進(jìn)程是否是主進(jìn)程,cluster.isWorker 用來判斷當(dāng)前進(jìn)程是否是工作進(jìn)程,兩者返回的都是布爾值。

workers

cluster.workers 是一個(gè)包含所有 worker 進(jìn)程的對(duì)象,key 為 worker.id,value 為 worker 進(jìn)程對(duì)象。

// 遍歷所有 workers
function eachWorker(callback) {
 for (const id in cluster.workers) {
 callback(cluster.workers[id]);
 }
}
eachWorker((worker) => {
 worker.send('big announcement to all workers');
});

fork([env])

cluster.fork() 方法用來新建一個(gè) worker 進(jìn)程,默認(rèn)上下文復(fù)制主進(jìn)程,只有主進(jìn)程可調(diào)用。

常用事件

listening

在工作進(jìn)程調(diào)用 listen 方法后,會(huì)觸發(fā)一個(gè) listening 事件,這個(gè)事件可以被 cluster.on('listening') 監(jiān)聽。

比如每當(dāng)一個(gè) worker 進(jìn)程連進(jìn)來時(shí),輸出一條 log 信息:

cluster.on('listening', (worker, address) => {
 console.log(
 `A worker is now connected to ${address.address}:${address.port}`);
});

exit

在工作進(jìn)程掛掉時(shí),會(huì)觸發(fā)一個(gè) exit 事件,這個(gè)事件可以被 cluster.on('exit') 監(jiān)聽。

比如自動(dòng)重啟 worker:

cluster.on('exit', (worker, code, signal) => {
 console.log('worker %d died (%s). restarting...',
 worker.process.pid, signal || code);
 cluster.fork();
});

worker 對(duì)象

worker 對(duì)象是 cluster.fork() 的返回值,代表一個(gè) worker 進(jìn)程。

worker.id

worker.id 是當(dāng)前 worker 的唯一標(biāo)識(shí),也是保存在 cluster.workers 中的 key 值。

worker.process

所有的 worker 進(jìn)程都是通過 child_process.fork() 生成的,這個(gè)進(jìn)程對(duì)象保存在 worker.process 中。

worker.send()

worker.send() 用在主進(jìn)程給子進(jìn)程發(fā)送消息,在子進(jìn)程中,使用 process.on() 監(jiān)聽消息并使用 process.send() 發(fā)送消息。

if (cluster.isMaster) {
 const worker = cluster.fork();
 worker.send('hi there');
} else if (cluster.isWorker) {
 process.on('message', (msg) => {
 process.send(msg);
 });
}

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • 詳解Node.js amqplib 連接 Rabbit MQ最佳實(shí)踐

    詳解Node.js amqplib 連接 Rabbit MQ最佳實(shí)踐

    這篇文章主要介紹了詳解Node.js amqplib 連接 Rabbit MQ最佳實(shí)踐,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-01-01
  • Puppeteer解決SEO問題方法

    Puppeteer解決SEO問題方法

    這篇文章主要為大家介紹了Puppeteer解決SEO問題方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • express框架,報(bào)錯(cuò):“Cannot set headers after they are sent to the client”,解決方法總結(jié)

    express框架,報(bào)錯(cuò):“Cannot set headers after t

    這篇文章主要介紹了express框架,報(bào)錯(cuò):“Cannot set headers after they are sent to the client”,解決方法,結(jié)合實(shí)例形式總結(jié)分析了常見的問題原因與對(duì)應(yīng)的解決方案,需要的朋友可以參考下
    2023-05-05
  • 垃圾回收器的相關(guān)知識(shí)點(diǎn)總結(jié)

    垃圾回收器的相關(guān)知識(shí)點(diǎn)總結(jié)

    本文是小編在網(wǎng)絡(luò)上整理的關(guān)于垃圾回收器的相關(guān)知識(shí)點(diǎn),很多語言和程序都用的到,有興趣的可以學(xué)習(xí)下。
    2018-05-05
  • Node.js  事件循環(huán)詳解及實(shí)例

    Node.js 事件循環(huán)詳解及實(shí)例

    這篇文章主要介紹了 Node.js 事件循環(huán)詳解及實(shí)例的相關(guān)資料,Node.js 有多個(gè)內(nèi)置的事件,我們可以通過引入 events 模塊,并通過實(shí)例化 EventEmitter 類來綁定和監(jiān)聽事件,需要的朋友可以參考下
    2017-08-08
  • 解決node修改后需頻繁手動(dòng)重啟的問題

    解決node修改后需頻繁手動(dòng)重啟的問題

    今天小編就為大家分享一篇解決node修改后需頻繁手動(dòng)重啟的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-05-05
  • node腳本實(shí)現(xiàn)自動(dòng)化簽到和抽獎(jiǎng)功能

    node腳本實(shí)現(xiàn)自動(dòng)化簽到和抽獎(jiǎng)功能

    本文主要介紹了node腳本實(shí)現(xiàn)自動(dòng)化簽到和抽獎(jiǎng)功能,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • 詳解nodeJS之路徑PATH模塊

    詳解nodeJS之路徑PATH模塊

    本篇文章主要介紹了詳解nodeJS之路徑PATH模塊 ,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-05-05
  • 詳解Node.js實(shí)現(xiàn)301、302重定向服務(wù)

    詳解Node.js實(shí)現(xiàn)301、302重定向服務(wù)

    這篇文章主要介紹了詳解Node.js實(shí)現(xiàn)301、302重定向服務(wù),詳細(xì)的介紹了用Nodejs的http模塊,實(shí)現(xiàn)一個(gè)301或302重定服務(wù)。
    2017-04-04
  • node.js中debug模塊的簡單介紹與使用

    node.js中debug模塊的簡單介紹與使用

    這篇文章主要介紹了node.js中debug模塊的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),相信會(huì)對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來跟著小編來一起看看吧。
    2017-04-04

最新評(píng)論

宁德市| 临江市| 栾川县| 浏阳市| 广平县| 南昌市| 南江县| 砀山县| 当雄县| 青田县| 潞西市| 汉沽区| 吴江市| 全椒县| 南平市| 都江堰市| 丰台区| 通化市| 海城市| 抚远县| 罗源县| 万年县| 彭州市| 韶山市| 高唐县| 静安区| 科尔| 黄大仙区| 宜良县| 达孜县| 南昌县| 收藏| 毕节市| 旌德县| 张家口市| 同仁县| 宁津县| 科技| 谢通门县| 广元市| 黑龙江省|