自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Node.js中的進(jìn)程與線程

開發(fā) 前端
Node特點(diǎn)主線程是單線程的 一個進(jìn)程只開一個主線程,基于事件驅(qū)動的、異步非阻塞I/O,可以應(yīng)用于高并發(fā)場景。

 [[400868]]

1. 回顧進(jìn)程和線程的定義

  • 進(jìn)程(Process)是計算機(jī)中的程序關(guān)于某數(shù)據(jù)集合上的一次運(yùn)行活動,是系統(tǒng)進(jìn)行資源分配和調(diào)度的基本單位。

  • 線程(Thread)是操作系統(tǒng)能夠進(jìn)行運(yùn)算調(diào)度的最小單位。它被包含在進(jìn)程之中,是進(jìn)程中的實際運(yùn)作單位。

2. Node.js的單線程

Node特點(diǎn)主線程是單線程的 一個進(jìn)程只開一個主線程,基于事件驅(qū)動的、異步非阻塞I/O,可以應(yīng)用于高并發(fā)場景。

Nodejs中沒有多線程,為了充分利用多核cpu,可以使用子進(jìn)程實現(xiàn)內(nèi)核的負(fù)載均衡,那我們就要解決以下問題:

  • Node.js 做耗時的計算時候阻塞問題。

  • Node.js如何開啟多進(jìn)程。

  • 開發(fā)過程中如何實現(xiàn)進(jìn)程守護(hù)。

3. 場景實例

  1. const http = require('http'); http.createServer((req,res)=>{     if(req.url === '/sum'){ // 求和         let sum = 0;         for(let i = 0 ; i < 10000000000 ;i++){             sum+=i;         }         res.end(sum+'')     }else{         res.end('end');     } }).listen(3000); // 這里我們先訪問/sum,在新建一個瀏覽器頁卡訪問/  // 會發(fā)現(xiàn)要等待/sum路徑處理后才能處理/路徑   

4. 開啟進(jìn)程

Node.js 進(jìn)程創(chuàng)建,是通過child_process模塊實現(xiàn)的:

  • child_process.spawn() 異步生成子進(jìn)程。

  • child_process.fork() 產(chǎn)生一個新的Node.js進(jìn)程,并使用建立的IPC通信通道調(diào)用指定的模塊,該通道允許在父級和子級之間發(fā)送消息。

  • child_process.exec() 產(chǎn)生一個shell并在該shell中運(yùn)行命令。

  • child_process.execFile() 無需產(chǎn)生shell。

4.1. spawn

spawn 產(chǎn)卵,可以通過此方法創(chuàng)建一個子進(jìn)程:

  1. let { spawn } = require("child_process"); let path = require("path"); // 通過node命令執(zhí)行sub_process.js文件 let childProcess = spawn("node",['sub_process.js'], {   cwd: path.resolve(__dirname, "test"), // 找文件的目錄是test目錄下   stdio: [0, 1, 2]  }); // 監(jiān)控錯誤 childProcess.on("error", function(err) {   console.log(err); }); // 監(jiān)聽關(guān)閉事件 childProcess.on("close", function() {   console.log("close"); }); // 監(jiān)聽退出事件 childProcess.on("exit", function() {   console.log("exit"); });  
  2. stido 這個屬性非常有特色,這里我們給了01,2這三個值分別對應(yīng)住進(jìn)程的 process.stdin , process.stdout 和 process.stderr 這代表著主進(jìn)程和子進(jìn)程共享標(biāo)準(zhǔn)輸入和輸出: 

 

  1. let childProcess = spawn("node",['sub_process.js'], {   cwd: path.resolve(__dirname, "test"), // 找文件的目錄是test目錄下   stdio: [0, 1, 2]  });  

可以在當(dāng)前進(jìn)程下打印 sub_process.js 執(zhí)行結(jié)果默認(rèn)在不提供stdio參數(shù)時為 stdio:['pipe'] ,也就是只能通過流的方式實現(xiàn)進(jìn)程之間的通信:

  1. let { spawn } = require("child_process"); let path = require("path"); // 通過node命令執(zhí)行sub_process.js文件 let childProcess = spawn("node",['sub_process.js'], {   cwd: path.resolve(__dirname, "test"),   stdio:['pipe'] // 通過流的方式 }); // 子進(jìn)程讀取寫入的數(shù)據(jù) childProcess.stdout.on('data',function(data){     console.log(data); }); // 子進(jìn)程像標(biāo)準(zhǔn)輸出中寫入 process.stdout.write('hello');  

使用 ipc 方式通信,設(shè)置值為 stdio:['pipe','pipe','pipe','ipc'] 可以通過 on('message') 和 send 方式進(jìn)行通信:

  1. let { spawn } = require("child_process"); let path = require("path"); // 通過node命令執(zhí)行sub_process.js文件 let childProcess = spawn("node",['sub_process.js'], {   cwd: path.resolve(__dirname, "test"),   stdio:['pipe','pipe','pipe','ipc'] // 通過流的方式 }); // 監(jiān)聽消息 childProcess.on('message',function(data){     console.log(data); }); // 發(fā)送消息 process.send('hello');  

還可以傳入 ignore 進(jìn)行忽略,傳入 inherit 表示默認(rèn)共享父進(jìn)程的標(biāo)準(zhǔn)輸入和輸出。

產(chǎn)生獨(dú)立進(jìn)程:

  1. let { spawn } = require("child_process"); let path = require("path"); // 通過node命令執(zhí)行sub_process.js文件 let child = spawn('node',['sub_process.js'],{     cwd:path.resolve(__dirname,'test'),     stdio: 'ignore',     detached:true // 獨(dú)立的線程 }); child.unref(); // 放棄控制  

4.2. fork

衍生新的進(jìn)程,默認(rèn)就可以通過 ipc 方式進(jìn)行通信:

  1. let { fork } = require("child_process"); let path = require("path"); // 通過node命令執(zhí)行sub_process.js文件 let childProcess = fork('sub_process.js', {   cwd: path.resolve(__dirname, "test"), }); childProcess.on('message',function(data){     console.log(data); });  

fork 是基于 spawn 的,可以多傳入一個 silent 屬性來設(shè)置是否共享輸入和輸出。

fork原理:

  1. function fork(filename,options){     let stdio = ['inherit','inherit','inherit']     if(options.silent){ // 如果是安靜的  就忽略子進(jìn)程的輸入和輸出         stdio = ['ignore','ignore','ignore']     }     stdio.push('ipc'); // 默認(rèn)支持ipc的方式     options.stdio = stdio     return spawn('node',[filename],options) }  

到了這里我們就可以解決“3.場景實例”中的場景實例了:

  1. const http = require('http'); const {fork} = require('child_process'); const path = require('path'); http.createServer((req,res)=>{     if(req.url === '/sum'){         let childProcess = fork('calc.js',{             cwd:path.resolve(__dirname,'test')         });         childProcess.on('message',function(data){             res.end(data+'');         })     }else{         res.end('ok');     } }).listen(3000);  

4.3. execFile

通過 node 指令,直接執(zhí)行某個文件:

  1. let childProcess = execFile("node",['./test/sub_process'],function(err,stdout,stdin){     console.log(stdout);  });  

內(nèi)部調(diào)用的是  spawn 方法。

4.4. exec

  1. let childProcess = exec("node './test/sub_process'",function(err,stdout,stdin){     console.log(stdout) });  

內(nèi)部調(diào)用的是 execFile ,其實以上三個方法都是基于 spawn 的。

5. cluster

Node.js的單個實例在單個線程中運(yùn)行。為了利用多核系統(tǒng),用戶有時會希望啟動Node.js進(jìn)程集群來處理負(fù)載。 自己通過進(jìn)程來實現(xiàn)集群。

子進(jìn)程與父進(jìn)程共享HTTP服務(wù)器 fork實現(xiàn):

  1. let http = require('http'); let {     fork } = require('child_process'); let fs = require('fs'); let net = require('net'); let path = require('path'); let child = fork(path.join(__dirname, '8.child.js')); let server = net.createServer(); server.listen(8080'127.0.0.1', function () {     child.send('server', server);     console.log('父進(jìn)程中的服務(wù)器已經(jīng)創(chuàng)建');     let httpServer = http.createServer();     httpServer.on('request', function (req, res) {         if (req.url != '/favicon.ico') {             let sum = 0;             for (let i = 0; i < 100000; i++) {                 sum += 1;             }             res.write('客戶端請求在父進(jìn)程中被處理。');             res.end('sum=' + sum);         }     });     httpServer.listen(server); });  

 

  1. let http = require('http'); process.on('message', function (msg, server) {     if (msg == 'server') {         console.log('子進(jìn)程中的服務(wù)器已經(jīng)被創(chuàng)建');         let httpServer = http.createServer();         httpServer.on('request', function (req, res) {             if (req.url != '/favicon.ico') {                 sum = 0;                 for (let i = 0; i < 10000; i++) {                     sum += i;                 }                 res.write('客戶端請求在子進(jìn)程中被處理');                 res.end('sum=' + sum);             }         });         httpServer.listen(server);     } });  

進(jìn)程與父進(jìn)程共享socket對象:

  1. let {     fork } = require('child_process'); let path = require('path'); let child = fork(path.join(__dirname, '11.socket.js')); let server = require('net').createServer(); server.on('connection', function (socket) {     if (Date.now() % 2 == 0) {         child.send('socket', socket);     } else {         socket.end('客戶端請求被父進(jìn)程處理!');     } }); server.listen(41234, );  

 

  1. process.on('message', function (m, socket) {     if (m === 'socket') {         socket.end('客戶端請求被子進(jìn)程處理.');     } });  

使用cluster模塊更加方便:

  1. let cluster = require("cluster"); let http = require("http"); let cpus = require("os").cpus(). 

 

責(zé)任編輯:張燕妮 來源: 騰訊IMWeb前端團(tuán)隊
相關(guān)推薦

2021-04-20 12:39:52

Node.js多線程多進(jìn)程

2021-08-04 23:30:28

Node.js開發(fā)線程

2019-03-29 16:40:02

Node.js多線程前端

2019-08-15 14:42:24

進(jìn)程線程javascript

2022-06-23 06:34:56

Node.js子線程

2021-03-09 08:03:21

Node.js 線程JavaScript

2024-01-05 08:49:15

Node.js異步編程

2016-08-11 14:02:02

NodeJS前端

2020-04-15 15:48:03

Node.jsstream前端

2022-10-28 15:51:24

JavaScript開發(fā)Node.js

2013-11-01 09:34:56

Node.js技術(shù)

2015-03-10 10:59:18

Node.js開發(fā)指南基礎(chǔ)介紹

2022-01-29 22:27:31

內(nèi)核子線程應(yīng)用

2017-03-19 16:40:28

漏洞Node.js內(nèi)存泄漏

2017-03-20 13:43:51

Node.js內(nèi)存泄漏

2011-09-08 10:32:27

Node.js

2020-05-29 15:33:28

Node.js框架JavaScript

2021-12-25 22:29:57

Node.js 微任務(wù)處理事件循環(huán)

2012-02-03 09:25:39

Node.js

2021-03-04 23:12:57

Node.js異步迭代器開發(fā)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號