Node.js runs typically runs on a single thread, and doesn't take advantage of the multiple cores that might be available within a system. It can actually handle a pretty large volume of requests with a single process due to its event-driven, asynchronous architecture. However, apps that receive heavy traffic stand to benefit greatly from using all available system cores.

Node.js cluster module

Node.js ships with a core cluster module, which allows an application to run on more than one core and achieve greater concurrency so that it can handle more load.

The cluster module sets up a master process, which will fork your app into different processes called workers. It then uses a round-robin algorithm to distribute load amongst all the workers. When the master process receives a connection, it delegates the connections to a worker by sending that worker a TCP handle for the connection.

This is pretty easy to set up in your application. Here's an example of a clustered Express app:

var express = require('express'),
    cluster = require('cluster'),
    os = require('os');

  // If in the master process, create a worker for each CPU.
  if (cluster.isMaster) {
    for (var i = 0; i < os.cpus().length; i += 1) {
      cluster.fork();
    }

    // When process dies, replace it.
    cluster.on('exit', function () {
      cluster.fork();
    });

    return;
  }

  // This is a worker, because cluster.isMaster is false,
  // and so the conditional above will never run.
  // Let's just initialize Express and create a basic route.
  var app = express();
  app.listen(3000);

  app.get('/clustered', function (req, res) {
    res.send('Running on worker with id #' + cluster.worker.id);
  });

The first segment of this example creates workers each available core. The second segment is what actually runs within a worker. If you run this application, and visit the localhost:3000/clustered in a couple different browsers, you should see the worker id change.

Clustering with PM2

PM2 is a process manager for Node.js with a build-in load balancer, a keep-alive mechanism, and a large number of other administrative tools. It will handle clustering for you.

PM2 is really easy to use, and it contains a lot of super useful tools. I'd encourage you to read through the docs, but here's our example being clustered and load-balanced with PM2:

var app = express();

app.listen(3000);

app.get('/clustered', function (req, res) {
  res.send('Balanced and clustered via PM2');
});

Then we run this application with PM2:

pm2 start myAppEntry.js

That's it! And of course, PM2 is a box with a number of great tools that I won't go into detail here, but encourage you to go check it out.

Overall, clustering can really improve the concurrency and overall performance of your application, and it's really easy to set up. Go try it out!

Tags: