Posted by H-AZAD
Worker processes in clustered apps can crash without affecting the rest of the processes. Aside from the performance benefits, another reason to create a cluster of app processes is to isolate failures. Consistently report the event and use the cluster.fork() to start a new worker process whenever a worker process crashes.
Let's create a new directory, call it node-cluster-app or something like that. Then open CLI and run the command:
npm init
Fill all the information in cli, then install express package, run command:
npm install express
This is a basic app.js file:
const express = require('express');
const app = express();
app.get('/', (request, response, nextHandler) => {
response.send('Hello World!');
console.log(`Served by worker with process id (PID) ${process.pid}.`);
});
const server = require('http').createServer(app);
server.on('listening', () => {
console.log("App listening on port 3000");
})
server.listen(3000);
Now we can run it via
node ./app.js
And we should get an output like:
App listening or port 3000
And when you navigate to http://localhost:3000
or run command
curl localhost:3000/
We should see "Hello World!" as a response and the console will show:
Served by worker with process id (PID) XXXX.
The next step is creating a cluster.js file in same directory as the preceding step.
const cluster = require('cluster');
const os = require('os');
if (cluster.isMaster) {
// Get number of CPU core
const cpus = os.cpus().length;
console.log(`Number of Cluster: ${cpus}`)
for (let i = 0; i < cpus; i++) {
cluster.fork();
}
// set console's directory where we can see output from workers
console.dir(cluster.workers, {depth: 0});
// initialize our CLI
process.stdin.on('data', (data) => {
initControlCommands(data);
})
cluster.on('exit', (worker, code) => {
// Good exit code is 0 :))
// exitedAfterDisconnect ensures that it is not killed by master cluster or manually
// if we kill it via .kill or .disconnect it will be set to true
// \x1b[XXm represents a color, and [0m represent the end of this
//color in the console ( 0m sets it to white again )
if (code !== 0 && !worker.exitedAfterDisconnect) {
console.log(`\x1b[34mWorker ${worker.process.pid} crashed.\nStarting a new worker...\n\x1b[0m`);
const nw = cluster.fork();
console.log(`\x1b[32mWorker ${nw.process.pid} will replace him \x1b[0m`);
}
});
console.log(`Master PID: ${process.pid}`)
} else {
// how funny, this is all needed for workers to start
require('./app.js');
}
Now we can run our application as a cluster by typing:
node cluster.js
output should like this:
Number of Cluster: 8
{
'1': [Worker],
'2': [Worker],
'3': [Worker],
'4': [Worker],
'5': [Worker],
'6': [Worker],
'7': [Worker],
'8': [Worker]
}
Master PID: 17780
App listening on port 3000
App listening on port 3000
App listening on port 3000
App listening on port 3000
App listening on port 3000
App listening on port 3000
App listening on port 3000
App listening on port 3000
Worker 17788 crashed.
Starting a new worker...
Worker 17846 will replace him
App listening on port 3000
Worker 17794 crashed.
Starting a new worker...
Worker 17856 will replace him
Worker 17804 crashed.
Starting a new worker...
Worker 17864 will replace him
App listening on port 3000
App listening on port 3000
The app.js is now running as cluster. This is how we can increase our node.js and express.js app performance.