Show Buttons
Share On Facebook
Share On Twitter
Share On Google Plus
Share On Linkdin
Share On Reddit
Share On Stumbleupon
Contact us
Hide Buttons

Scaling a basic nodejs application using clusters

Nodejs derives is power from the asyn­chro­nous nature of javascript. How­ever, the lan­guage also has one major caveat — its sin­gle threaded nature. This directly impacts the scal­a­bil­ity in nodejs appli­ca­tions because if some of your requests con­sume con­sid­er­able proces­sor time then your thread is blocked and wont be able to process other incom­ing requests.

If you have a machine with mul­ti­ple cores, you can take advan­tage of this archi­tec­ture by spawn­ing mul­ti­ple nodejs processes upto as many cpu’s as are avail­able to you such that each of these node processes lis­ten on the same port. Such an arrange­ment is known as a nodejs cluster.

On a linux machine, you can sim­ply run the fol­low­ing com­mand to check how many CPU’s are avail­able to you

nproc

If your num­ber is greater than 1, then you are in good luck because now you can spawn mul­ti­ple nodejs processes.


Ini­tial setup

Lets first setup our package.json file. We will use expressjs to han­dle our requests.

{
    "name": "node-cluster-example",
    "version": "0.0.1"
}

Now install the lat­est ver­sion of express using

npm install express --save

Mas­ter and worker threads

Before we write our app.js file, there are 4 impor­tant things that you need to know.

  1. The process that runs as a result of run­ning the node server from the com­mand line becomes the mas­ter thread.
  2. The nodejs cluster mod­ule can be used within your code to dis­tin­guish between the mas­ter thread and worker threads.
  3. If the mas­ter thread is killed, so are the worker threads.
  4. When a worker thread exits unex­pect­edly, it fires an ‘exit’ event. You can lis­ten to this event to spawn another thread if needed.

Below is the code we can use to setup a sim­ple nodejs cluster

var cluster = require('cluster');
var express = require('express');
var app = express();
var port = 3000;
var cpus;
var i;

if (cluster.isMaster) {
  // The master thread is assigned the sole responsibility
  // of spawning child threads
  cpus = require('os').cpus().length;

  for (i = 0; i < cpus; i += 1) {
    // Here we create one worker thread per CPU
    cluster.fork();
  }

  cluster.on('exit', function (worker) {
      console.log('Worker ' + worker.id + ' exited');
      cluster.fork();
  });

} else {
  // Our app is initialized only on worker threads
  app = express();

  app.get('/', function (req, res) {
    res.send('Hello!, I am Worker #' + cluster.worker.id);
  });

  app.listen();
  console.log('App listening on port : ' + port);
}

Now you can sim­ply run your app from the shell using

node app

And you will see as many App is listening on port mes­sages as there are CPU’s on your machine.


Ryan Sukale

Ryan is a UX engineer living in San Francisco, California.