var Promise = require('bluebird'); var fiboTasks = [44, 42, 42, 43]; function fibo(n) { return n == 0 ? 0 : n > 1 ? fibo(n - 1) + fibo(n - 2) : 1; } function excuteFibo(seq, taskID) { return new Promise((resolve) => { setTimeout(() => { var st = Date.now(); var result = fibo(seq); console.log(`Task ${taskID} was complete and using ${Date.now() - st} ms`); resolve(result); }, Math.random()*10); }); } var st = Date.now(); Promise.map(fiboTasks, function (item, index) { return excuteFibo(item, index) }).then(function (result) { console.log(`All tasks were complete and using ${Date.now() - st} ms`); })
Show moreShow more icon
首先,为了让 CPU 忙起来,这里用了大家喜闻乐见的斐波那契数列函数,用来来模拟一个消耗 CPU 的应用。
c:\work\NodeClusterTest>node concurrentTest.js Task 0 was complete 701408733 and using 11971 ms Task 3 was complete 433494437 and using 7272 ms Task 1 was complete 267914296 and using 4477 ms Task 2 was complete 267914296 and using 4573 ms All tasks were complete and using 28308 ms
if (cluster.isMaster) { var collection = [44, 42, 42, 43]; var st = Date.now(); for (var i = 0; i < Math.min(numCPUs, collection.length); i++) { var wk = cluster.fork(); wk.send(collection[i]); } cluster.on('fork', function (worker) { console.log(`[master] : fork worker ${worker.id}`); }); cluster.on('exit', function (worker, code, signal) { console.log(`[master] : worker ${worker.id} died`); }); var numOfCompelete = 0 Object.keys(cluster.workers).forEach(function (id) { cluster.workers[id].on('message', function (msg) { console.log(`[master] receive message from [worker ${id}]: ${msg}`); numOfCompelete++; if (numOfCompelete === collection.length) { console.log(`[master] finish all work and using ${Date.now() - st} ms`); cluster.disconnect(); } }); });
} else { process.on('message', function (msg) { var st = Date.now(); var result = fibo(msg); console.log(`[worker ${cluster.worker.id}] finish work and using ${Date.now() - st} ms`); process.send(result); }); }
C:\work\NodeClusterTest> node test.js ####====START====### [master] : fork worker 1 [master] : fork worker 2 [master] : fork worker 3 [master] : fork worker 4 ####====START====### ####====START====### ####====START====### ####====START====### [worker 2] finish work and using 9284 ms [master] receive message from [worker 2]: 267914296 [worker 3] finish work and using 9456 ms [master] receive message from [worker 3]: 267914296 [worker 4] finish work and using 13030 ms [master] receive message from [worker 4]: 433494437 [worker 1] finish work and using 17632 ms [master] receive message from [worker 1]: 701408733 [master] finish all work and using 18099 ms [master] : worker 4 died [master] : worker 3 died [master] : worker 2 died [master] : worker 1 died
var cluster = require('cluster'); function fibo(n) {...} console.log(`[worker ${cluster.worker.id}] start ...` ); process.on('message', function(msg) { var st = Date.now(); console.log(`[worker ${cluster.worker.id}] start to work`); var result = worker.fibo(msg); console.log(`[worker ${cluster.worker.id}] work finish work and using ${Date.now() - st} ms`); process.send(result); });
var exuteFibo = require('./master'); console.log('=====Start========'); var st = Date.now(); exuteFibo().then(function(result){ console.log(`Finish all work and using ${Date.now() - st}`); console.log('####Get result from multiple-processes: '+ result); });
Show moreShow more icon
同样的,还是来看一下具体的执行结果:
清单 10.main.js 代码执行结果
1 2 3 4 5 6 7 8 9 10 11 12
PS C:\work\NodeClusterTest> node .\main.js =====Start======== [master] : fork worker 1 ...... [master] finish all work and using 17357 ms Finish all work and using 17365 ####Get result from multiple-processes: 433494437,433494437,701408733,1134903170 [master] : worker 4 died [master] : worker 3 died [master] : worker 1 died [master] : worker 2 died
var exuteFibo = require('./master'); console.log('=====Start========'); var st = Date.now(); exuteFibo().then(function(result){ console.log(`Finish all work and using ${Date.now() - st}`); console.log('####Get result from multiple-processes: '+ result); });
st = Date.now(); exuteFibo().then(function(result){ console.log(`Finish all work and using ${Date.now() - st}`); console.log('####Get result1 from mutliple-processes: '+ result); });
...... [worker 6] start to work [worker 3] work finish work and using 17823 ms [master] receive message from [worker3]: 433494437 ...... [master] receive message from [worker6]: 433494437 [master] finish all work and using 19618 ms Finish all work and using 19634 [master] : worker 3 died [master] : worker 3 died [master] : worker 7 died [master] : worker 7 died ③ [master] : worker 6 died [master] : worker 6 died [master] : worker 2 died [master] : worker 2 died [worker 8] work finish work and using 24262 ms [master] receive message from [worker8]: 701408733 [master] : worker 8 died [master] : worker 8 died [worker 4] work finish work and using 23825 ms [master] receive message from [worker4]: 701408733 [master] receive message from [worker4]: 701408733 [master] : worker 4 died [master] : worker 4 died [worker 1] work finish work and using 28957 ms [master] receive message from [worker1]: 1134903170 [master] finish all work and using 29816 ms events.js:141 throw er; // Unhandled 'error' event ④ ^ Error: write EPIPE at exports._errnoException (util.js:874:11)
Show moreShow more icon
基本上,从日志中可以发现有四处很明显的问题:
每一个 worker 进程似乎被 fork 了两次
Worker 的 id 最大为什么会是 8?我们的 master 进程可只 fork 了 4 个 work 进程
“Node.js does not automatically manage the number of workers for you, however. It is your responsibility to manage the worker pool for your application’s needs “
PS C:\work\NodeClusterTest> node .\main.js =====Start======== [master 11796] : fork worker 1 [master 11796] : fork worker 2 [master 11796] : fork worker 3 [master 11796] : fork worker 4 ....... [master 11796] finish all work and using 26499 ms Finish all work and using 26499 ####Get result1 from mutliple-processes: 165580141,433494437,701408733,1134903170 [master 11796] : worker 6 died [master 11796] : worker 5 died [master 11796] : worker 7 died [master 11796] : worker 8 died [worker 1] work finish work and using 25670 ms [master 11796] receive message from [worker1]: 1134903170 [master 11796] finish all work and using 26631 ms Finish all work and using 26561 ####Get result from mutliple-processes: 165580141,433494437,701408733,1134903170 [master 11796] : worker 1 died [master 11796] : worker 2 died [master 11796] : worker 3 died [master 11796] : worker 4 died
Reprint policy:
All articles in this blog are used except for special statements
CC BY 4.0
reprint policy. If reproduced, please indicate source
John Doe
!