Nodejs cluster: why blocking master will block workers too? - node.js

As you can see, in master(cluster.isMaster) while loop is blocking master, but why worker is also blocked?
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
const sleep = require('sleep');
if (cluster.isMaster) {
console.log(`Master ${process.pid} is running`);
// Fork workers.
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`worker ${worker.process.pid} died`);
});
// background jobs start
while(true) {
console.log(123)
sleep.sleep(1) // do_background_jobs()
}
// background jobs end
} else {
// Workers can share any TCP connection
// In this case it is an HTTP server
http.createServer((req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);
console.log(`Worker ${process.pid} started`);
}
Here is logs:
Master 45476 is running
Worker 45479 started
Worker 45483 started
Worker 45482 started
Worker 45478 started
But netstat shows 8000 is closed. of cource curl fails.

Related

How can a run a middleware function a single time when I am using Cluster in Node.js

I am using clusters in my node.js server and I have a middlewere function that is saving weekly some data to db. The issue is that I am using three workers and this function is executed three times and it saves 3 documents in the DB. How can I avoid this and still use clusters?
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log(`Master ${process.pid} is running`);
// execute the one time function
// Fork workers.
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`worker ${worker.process.pid} died`);
});
} else {
// Workers can share any TCP connection
// In this case it is an HTTP server
http.createServer((req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);
console.log(`Worker ${process.pid} started`);
}
you can do that by executing it inside the if statement or where your master code executes. this way you can just run it once.
https://nodejs.org/api/cluster.html
Your nodejs program can tell whether it's the master with cluster.isMaster().
Your master can update your weekly data. Or, if all your workers have to generate their own data, they can do that, then the master can read it all and create just one document.

Can node run in multiple threads?

Nodejs is asynchronous. But single threaded. When a synchronous workload is executed, the event loop is blocked.
Can we make node multi threaded to increase performance?
You can look into cluster mode in recent versions of Node.js.
Quoting the example from the above page for reference:
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log(`Master ${process.pid} is running`);
// Fork workers.
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`worker ${worker.process.pid} died`);
});
} else {
// Workers can share any TCP connection
// In this case it is an HTTP server
http.createServer((req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);
console.log(`Worker ${process.pid} started`);
}
This code starts a number of workers, and you see a clear separation between master and worker code.
These processes can communicate by sending messages.

How can i take the advantage of multi-core systems in node using cluster module

I read the cluster module from documentation of nodejs according to my understanding we can use this module to take advantage of multi-core systems
i.e
i can easily handle the load, means more number of hits on my system on same port but using different cpu's
for ensuring this i am just doing a simple test at my system
here is my code with cluster module
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
const express = require('express');
const path = require('path');
const servers = [];
const workers = [];
if (cluster.isMaster) {
console.log(`Master ${process.pid} is running`);
console.log("total no of cpus", numCPUs);
// Fork workers.
for (let i = 0; i < numCPUs; i++) {
workers.push(cluster.fork());
workers[i].on('listening', (address) => {
console.log("address", JSON.stringify(address));
});
}
cluster.on('exit', (worker, code, signal) => {
console.log(`worker ${worker.process.pid} died`);
});
} else {
let app = express();
// Workers can share any TCP connection
app.listen(2121, (serverInfo) => {
console.log("server listening at port 2121", JSON.stringify(serverInfo));
})
app.get('/',(req,res,next)=>{
res.json({success:'success'})
})
app.use(express.static(path.join(__dirname)))
app.get('/loaderio-edc7fc83ca1554036ee53a6807d5efb5', (req, res, next) => {
res.sendFile('./loaderio-edc7fc83ca1554036ee53a6807d5efb5.txt')
})
console.log(`Worker ${process.pid} started`);
}
and here is the code of without clustering
const express = require('express');
let app = express();
const path = require('path');
app.listen(2121 , (serverInfo) => {
console.log("server listening at port 2121", JSON.stringify(serverInfo));
})
app.get('/',(req,res,next)=>{
res.json({success:'success'})
})
app.use(express.static(path.join(__dirname)))
app.get('/loaderio-edc7fc83ca1554036ee53a6807d5efb5', (req, res, next) => {
res.sendFile('./loaderio-edc7fc83ca1554036ee53a6807d5efb5.txt')
})
And I just test it by loader.io i got the test results as below:
result using cluster module
result using without cluster module
I am not getting the results as i want
i got 24 timeouts in using cluster module
is my approach isn't correct if yes then how can i take the more advantages of multi-core systems in nodejs or is here anything that i missed?.
try this
if (cluster.isMaster) {
console.log(`Master ${process.pid} is running in mode: ` + (process.env.NODE_ENV || 'dev'));
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`worker ${worker.process.pid} died, restarting!`);
cluster.fork();
});
} else {
app.listen(PORT)
console.log(`worker ${process.pid} started`);
console.log('Listening on port ' + PORT);
}

using nodejs cluster in production?

i was reading nodejs cluster to run multiple instances of node appication
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log(`Master ${process.pid} is running`);
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`worker ${worker.process.pid} died`);
});
}
else {
http.createServer((req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);
console.log(`Worker ${process.pid} started`);
}
is using this approach good in a production environment.
where the number of requests is more
You can rather use pm2/strongloop for managing this.Because all these modules are production ready and really easy to manage.
I personally feel pm2 is awesome to manage node processes.
Use following link to know more about pm2
http://pm2.keymetrics.io/
Yes you can use cluster for as long as you are calculating your cpu length
const numCPUs = require('os').cpus().length;
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
The cluster won't create processes more than that of the cpu length
But if clusters are not manage properly it will slow down the entire application process

Node's Cluster Fork

I don't understand how clusters work in Node.
The snippet below is example code from Node's docs.
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log(`Master ${process.pid} is running`);
// Fork workers.
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`worker ${worker.process.pid} died`);
});
} else {
// Workers can share any TCP connection
// In this case it is an HTTP server
http.createServer((req, res) => {
res.writeHead(200);
res.end('hello world\n');
}).listen(8000);
console.log(`Worker ${process.pid} started`);
}
I'd like to know exactly what happens at cluster.fork(). Does it copy over any variables to the forked processes? If I declared an object before forking, would both threads access it? Is it possible to assign tasks to a thread manually or does Node have to do it?

Resources