Blog Post

No logo
Cluster

What is cluster?

A single instance of Node.js runs in a single thread. To take advantage of multi-core systems, the user will sometimes want to launch a cluster of Node.js processes to handle the load. The cluster module allows easy creation of child processes that all share server ports.

EXAMPLE:

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`);

}

OUTPUT:

Master 3596 is running

Worker 4324 started

Worker 4520 started

Worker 6056 started

How It Works?

The cluster module supports two methods of distributing incoming connections.

The first one (and the default one on all platforms except Windows), is the round-robin approach, where the master process listens on a port, accepts new connections and distributes them across the workers in a round-robin fashion, with some built-in smarts to avoid overloading a worker process.

The second approach is where the master process creates the listen socket and sends it to interested workers. The workers then accept incoming connections directly.

Below is the some class and event in cluster:

Class: Worker

A Worker object contains all public information and method about a worker. In the master it can be obtained using cluster.workers. In a worker it can be obtained using cluster.worker.

Event:’Disconnect’

Emitted after the worker IPC channel has disconnected. This can occur when a worker exits gracefully, is killed, or is disconnected manually (such as with worker.disconnect())

cluster.on('disconnect', (worker) => {

  console.log(`The worker #${worker.id} has disconnected`);

});

Event: 'exit'

     When any of the workers die the cluster module will emit the 'exit' event.

     This can be used to restart the worker by calling .fork() again.

cluster.on('exit', (worker, code, signal) => {

  console.log('worker %d died (%s). restarting...', worker.process.pid, signal || code);

  cluster.fork();

});

Event: 'fork'

      When a new worker is forked the cluster module will emit a 'fork' event. This can be used to log worker activity, and create a custom timeout.

const timeouts = [];

function errorMsg() {

  console.error('Something must be wrong with the connection ...');

}

cluster.on('fork', (worker) => {

  timeouts[worker.id] = setTimeout(errorMsg, 2000);

});

cluster.on('listening', (worker, address) => {

  clearTimeout(timeouts[worker.id]);

});

cluster.on('exit', (worker, code, signal) => {

  clearTimeout(timeouts[worker.id]);

  errorMsg();

});