Cluster and Child_process
https://nodejs.org/api/cluster.html
因為Nodejs為單進程,所以預設只會用一個CPU執行程式,所以我們可以用Cluster來讓他可以跑多個CPU
1.以下為讓每個cpu都跑一個process的範例(根據cpu數量)
var cluster = require('cluster');
var os = require('os');
if (cluster.isMaster){
for (var i = 0, n = os.cpus().length; i < n; i += 1){
cluster.fork();
}
} else {
http.createServer(function(req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8000);
}
2.以下為讓子進程與主進程溝通的範例
var cluster = require('cluster');
var http = require('http');
var numReqs = 0;
var workers = [];
if (cluster.isMaster) {
// Broadcast a message to all workers
var broadcast = function() {
for (var i in workers) {
var worker = workers[i];
worker.send({ cmd: 'broadcast', numReqs: numReqs }); //send裡面可以隨便放
}
}
// Fork workers.
for (var i = 0; i < 2; i++) {
var worker = cluster.fork();
worker.on('message', function(msg) {
if (msg.cmd) {
switch (msg.cmd) {
case 'notifyRequest':
numReqs++;
break;
case 'broadcast':
broadcast();
break;
}
});
// Add the worker to an array of known workers
workers.push(worker);
}
setInterval(function() {
console.log("numReqs =", numReqs);
}, 1000);
} else {
// React to messages received from master
process.on('message', function(msg) {
switch(msg.cmd) {
case 'broadcast':
if (msg.numReqs) console.log('Number of requests: ' + msg.numReqs);
break;
}
});
// Worker processes have a http server.
http.Server(function(req, res) {
res.writeHead(200);
res.end("hello world\n");
// Send message to master process
process.send({ cmd: 'notifyRequest' });
process.send({ cmd: 'broadcast' });
}).listen(8000);
}
但是
master 進程創建 socket,綁定到某個地址以及PORT後,自身不調用 listen 來監聽連接以及 accept 連接,而是將該 socket 的 fd(file descriptor) 傳遞到 fork 出來的 worker 進程,worker 接收到 fd 後再調用 listen,accept 新的連接。但實際一個新到來的連接最終只能被某一個 worker 進程 accpet 再做處理。
所以會造成子進程產生競爭現象
執行shell指令
可以使用spawn或是exec
Exec
const { exec } = require('child_process');
exec(`
mkdir ${location}
cd ${location}
openssl genrsa -out ${keyName}_private.pem
openssl rsa -in ${keyName}_private.pem -out ${keyName}_public.pem -outform PEM -pubout
`, (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`${stdout}`);
console.log(`${stderr}`);
});
Spawn
spawn會需要將參數寫成如下
const spawn = require('child_process').spawn;
const ls = spawn('ls', ['-lh', '/usr']);
如果有輸出log
const { exec } = require('child_process');
const cmdInfo = exec(`ls -lh`);
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}`);
});
Last updated
Was this helpful?