您好,登錄后才能下訂單哦!
本篇文章為大家展示了nodejs中怎么利用cluster實現多進程,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
node進行多進程的模塊;
isMaster屬性,返回是不是主進程,boolean值;
isWorker屬性, 返回該進程是不是工作進程;
fork()方法,只能通過主進程調用,衍生出一個新的worker子進程,返回worker對象;
setupMaster([setting])方法,用于修改fork的默認行為,一旦調用,將會按照cluster.settings進行設置;
settings屬性;用于配置;
參數exec:worker文件路徑,
args:傳遞給worker的參數;
execArgv: 傳遞給nodejs可執行文件的參數列表;
const cluster = require('cluster'); const cpuNums = require('os').cpus().length; const http = require('http'); if (cluster.isMaster) { console.log(cpuNums); for (var i = 0; i < cpuNums; i++) { cluster.fork(); // 相當于node main.js,重新執行自己 // 和process_child相比,不用重新創建child.js, } cluster.on('fork', worker => { console.log(`主進程fork了一個worker,pid為${worker.process.pid}`) }) cluster.on('listening', worker => { console.log(`主進程fork了一個worker,pid為${worker.process.pid}`) }) cluster.on('message', data => { console.log('主進程接收到了子進程消息為:',data) }) Object.keys(cluster.workers).forEach(item => { cluster.workers[item].on('message', data => { console.log(data); }); }); cluster.on('disconnect', (worker) => { console.log('有工作進程退出了',worker.process.pid) }) } else { http.createServer((req, res) => { res.end('hello') }).listen(8001, () =>{ console.log('child server is runing') }) console.log('我是子進程'); process.send('子說:你好'); }
fork事件,當新的工作進程被fork時觸發,可以用來記錄工作進程活動;
listening事件,當一個工作進程調用listen()后觸發,事件處理器兩個參數:worker:工作進程對象, address:包含了鏈接屬性
只有http的服務的listen事件才能觸發此事件
message事件,監聽子進程的消息;當cluster主進程接收任何工作進程發送的消息時觸發;
比較特殊需要在單獨的worker上監聽;
online事件,
disconnect事件,當工作進程斷開時調用;
exit事件,
setup事件,cluster.setupMaster()執行后觸發;
每個worker進程通過使用cluster.fork()函數,基于IPC(Inter-Process-Communication),實現與master進程間通信;
那通過child_process.fork()直接創建不就可以了,為什么要通過cluster
這種方式只實現了多進程,多進程運行還涉及父子進程通信,子進程管理,以及負載均衡等問題,這些特性cluster已經做了處理了;
多個進程間會競爭一個accept連接,產生驚群現象,效率比較低;
由于無法控制一個新的連接由哪個進程來處理,導致worker進程間負載不均衡;
master.js
const net = require('net'); // 是最基礎的網絡模塊,http的基礎就是網絡模塊,最底層是socket const fork = require('child_process').fork; // 驚群 var handle = net._createServerHandle('0.0.0.0', 5000); // net模塊創建一個服務,綁定到3000端口,返回一個callback for (var i = 0; i < 4; i++) { console.log('fork', i); fork('./worket.js').send({}, handle); // 主進程fork子進程,send信息 }
worker.js
const net = require('net'); process.on('message', (m, handle) => { // 子進程接收到master信息 // master接收客戶端的請求,worker去響應 start(handle); }); var buf = 'hello nodejs'; var res = ['HTTP/1.1 200 OK', 'content-length' + buf.length].join('\r\n') + ' \r\n\r\n' + buf; var data = {}; function start(server) { // 響應邏輯,重點關注驚群效果,計數 server.listen(); server.onconnection = function(err, hand) { var pid = process.pid; if (!data[pid]) { data[pid] = 0; } data[pid]++; console.log('get a connection on worker,pid = %d', process.pid, data[pid]); var socket = net.Socket({ handle: hand }); socket.readable = socket.writable = true; // 修改socket的讀寫屬性 socket.end(res); }; }
Nginx 是俄羅斯人編寫的十分輕量級的http服務器,是一個高性能的HTTP和反向代理服務器,異步非阻塞I/O,而且能夠高并發;
正向代理:客戶端為代理,服務端不知道代理是誰;
反向代理:服務器為代理,客戶端不知道代理是誰;
nginx的實際應用場景: 比較適合穩定的服務
靜態資源服務器:js,css, html
企業級集群
守護進程:退出命令窗口之后,服務一直處于運行狀態;
cluster是由master監聽請求,在通過round-robin算法分發給各個worker,避免了驚群現象的發生;
round-robin 輪詢調度算法的原理是每一次把來自用戶的請求輪流分配給內部中的服務器;
cluster-model.js
const net = require('net'); const fork = require('child_process').fork; // cluster 簡單版本,cluster就是基于child_process去封裝的; var workers = []; for (var i = 0; i < 4; i++) { workers.push(fork('./child')); // cluster workers } var handle = net._createServerHandle('0.0.0.0', 3001); // master handle.listen(); handle.onconnection = function(err, handle) { var worker = workers.pop(); worker.send({}, handle); workers.unshift(worker); // 通過pop 和 unshift實現一個簡單的輪詢 };
child.js
const net = require('net'); process.on('message', (m, handle) => { debugger; start(handle); }); var buf = 'hello cluster'; var res = ['HTTP/1.1 200 OK', 'content-length' + buf.length].join('\r\n') + '\r\n\r\n' + buf; function start(handle) { console.log('get a worker on server,pid = ' + process.pid); var socket = net.Socket({ handle }); socket.readable = socket.writable = true; // 修改socket的讀寫屬性 socket.end(res); }
關閉異常worker進程所有的TCP server(將已有的快速斷開,且不再接受新的連接),斷開和Master的IPC通道,不再接受新的用戶請求;
Master立刻fork一個新的worker進程,保證總的進程數量不變;
異常worker等待一段時間,處理完已接受的請求后退出;
if(cluster.isMaster){ cluster.fork(); }else { // 出錯之后 try{ res.end(dddd); // 報錯,整個線程掛掉,不能提供服務, }catch(err){ // 斷開連接,斷開和Master的連接,守護進程其實就是重啟; process.disconnect(); // or exit() } }
Master進程除了接收新的連接,分發給各worker處理之外,還像天使一樣默默守護著這些進程,保障應用的穩定性,一旦某個worker進程退出就fork一個新的子進程頂替上去;
這一切cluster模塊已經處理好了,當某個worker進程發生異常退出或者與Master進程失去聯系(disconnected)時,master進程都會收到相應的事件通知;
cluster.on('exit',function(){ cluster.fork(); }) cluster.on('disconnect',function(){ cluster.fork(); })
IPC通信就是進程間的通信;
雖然每個worker進程是相對獨立的,但是他們之間還是需要通信的;叫進程間通信(IPC)通信;
worker和worker之間的通信通過Master轉發:通過worker的pid
const cluster = require('cluster'); if(cluster.isMaster){ var worker = cluster.fork(); worker.send('hi, i am master'); worker.on('message', (msg) =>{ console.log(`${msg} is from worker ${worker.id}`) }) }else if(cluster.isWorker){ process.on('message', (msg) =>{ process.send(msg); }) }
上述內容就是nodejs中怎么利用cluster實現多進程,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。