此章節一共分爲兩個章節,下一節,nodejs-第二章-第三節-nodejs多進程-cluster(2-2)node
- 進程是資源分配的最小單位,線程是CPU調度的最小單位
- 進程--資源分配最小單位,線程--程序諮詢最小單位
一個進程下面的線程是能夠去通訊的,共享資源算法
多進程和多線程通常能夠結合起來使用shell
對比維度 | 多進程 | 多線程 | 總結 |
---|---|---|---|
數據共享、同步 | 數據共享複雜,須要用IPC;數據是分開的,同步簡單 | 由於共享進程數據,數據共享簡單,但也是由於這個致使同步複雜 | 各有優點 |
內存、cpu | 佔用內存多,切換負責,cpu利用率低 | 佔用內存少,切換簡單,cpu利用率高 | 線程佔優 |
建立銷燬、切換 | 建立銷燬複雜,速度慢 | 建立銷燬簡單,速度很快 | 線程佔優 |
編程、調試 | 編程簡單,調試簡單 | 編程複雜、調試複雜 | 進程佔優 |
可靠性 | 進程間不會相互影響 | 一個線程掛掉將致使整個進程掛掉 | 進程佔優 |
分佈式 | 適應於多核、多機分佈式;若是一臺機器不夠,擴展到多臺機器比較簡單 | 適應於多核分佈式 | 進程佔優 |
利用cluster開啓多進程apache
const cluster = require('cluster'); // 多進程 const http = require('http'); const numCpus = require('os').cpus().length; // 獲取cpu的核數 if(cluster.isMaster){ // 是不是主線程 for(var i = 0; i < numCpus; i++){ cluster.fork() // 開啓子線程 cluster.on('exit', function(worker, code ,signal){ // 監測哪一個進程掛掉 console.log('worker'+worker.process.pid+'died') }) } } else { http.createServer((req,res) =>{ res.writeHead(200); res.end('hello world'); }).listen(8000) }
多進程的性能要明顯好於單進程編程
Process進程,child_process子進程,Cluster集羣json
process對象是Node的一個全局對象,提供當前Node進程的信息,它也能夠在腳本的任意位置使用,沒必要經過require獲取;數組
屬性瀏覽器
方法安全
事件bash
bbb() // 這裏會直接報錯,由於js是單線程的, // uncaughtException專門是捕捉異步代碼錯誤,特別是http process.on('uncaughtException', (err) =>{ console.log(err) })
const http = require('http'); http.createServer((req, res) => { ccc() }).listen(8000, () => { console.log(`server is runing on 8000`) }) process.on('uncaghtException', (err) => { // 這裏會捕獲ccc的異步錯誤s console.log('發生錯誤',err) })
node中用於建立子進程的模塊,cluster就是基於child_process模塊封裝的;
const exec = require('child_process').exec; // 1. 經過回調的方式接收結果 // exec('ls', (err, stdout, stderr) => { // // 在node中,容錯處理和業務代碼同樣重要; // // 由於js是單線程,一旦發生錯誤,後面代碼就不會執行 // if (err) { // console.log('stderr', stderr); // } // console.log('err', err); // console.log('stdout', stdout); // }); // 因爲標準輸出和標準錯誤都是流對象(stream),能夠監聽data事件 // 2. 經過流的方式返回結果, // 能夠一邊讀取一邊接收結果,不用等全部文件讀取完 var child = exec('lss'); child.stdout.on('data', data => { console.log(data); }); // 發生錯誤 child.stderr.on('data', err => { console.log('發生錯誤了', err); }); console.log(111)
var execSync('child_progress'); var path = '../' var child = execSync(`ls ${path} \ rm rf`); // 這樣會刪除此文件夾的上一級目錄的全部文件 console.log(child.toString());
const { execFile } = require('child_progress') execFile('ls', ['-c'], (err, stdout, stderr) => { console.log('stdout', stdout) })
const { spawn } = require('child_process'); let child = spawn('ls', ['-c']); child.stdout.on('data', data => { console.log('data', data.toString('utf8')); });
main.js
const child_process = require('child_process'); const path = require('path'); var child = child_process.fork(path.resolve(__dirname, './child.js')); child.on('message', data => { console.log('父接收到子消息:', data); }); child.send('父親send', data => { console.log('父親說:爲父給你發消息了'); });
child.js
process.on('message', data => { console.log('兒子接收到父親消息:', data); }); process.send('兒子send', data => { console.log('兒子對父親說:hello '); });