Boosting Nodejs ๐Ÿš€ using Node Clusters

ยท

2 min read

Boosting Nodejs ๐Ÿš€ using Node Clusters

Nodejs is Awesome!

What makes Nodejs great is not just that it's a javascript runtime but also its event-driven architecture and non-blocking IO.

In Nodejs

Almost everything except your code is concurrent

The code that you write is single-threaded.

If you have more than one core in the server, then you could speed it up by utilizing all the cores of the server.

One way to achieve it would be by spawning many Nodejs instances and load balancing the incoming request. This could get the job done but can we do better?

Nodejs Clusters

Nodejs has a feature called clusters which could be used to achieve the same.

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.

We'll use ES modules.

import cluster from 'cluster';

The main node process is used to create child processes (workers).

// Creates a Child process
cluster.fork()
// Check if process is primary
if (cluster.isPrimary) {
  console.log(`Primary ${process.pid} is running`);

  // Creates one worker process.
   cluster.fork();

} else {
  // Do whatever you want to do here
 //

  console.log(`Worker ${process.pid} started`);
}

How does it solve our problem though?

The child processes created using cluster.fork() can share any tcp connection! Making it possible for the workers to share the same port.

Since you cannot parallelize more than the number of CPU cores, spawning workers more than the number of CPU cores won't increase any performance.

The following snippet is from the official docs.

import cluster from 'cluster';
import http from 'http';
import { cpus } from 'os';
import process from 'process';

const numCPUs = cpus().length;

if (cluster.isPrimary) {
  console.log(`Primary ${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`);
}

References


Cover photo by Chris Liverani on Unsplash.