Last Updated: February 25, 2016
·
1.219K
· giulianoiacobel

Handling load in NodeJS

Node.js is one-thread-per-process but is absolutely does scale on multi-core machines.
This is a very deliberate design decision and eliminates the need to deal with locking semantics and I really love to not mess with multi-threaded code debugging.

So what about scaling on load with Node? Here are two simple and easy-to-setup options:

Reverse proxy with NGINX

Run your Node.js service behind a reverse-proxy like Nginx, good for connection throttling, rewrite URLs, serve static content (NGINX is far better than Node for this), and proxy other sub-services. Nginx will catch your traffic from port 80 and can be easily configured to route the requests to two node process running in different ports like this:

upstream app  {
  server localhost:8001;
  server localhost:8002;
}

server {
  location / {
    proxy_pass  http://app;
  }
}

and then launch your processes with node PORT=8001 app.js and node PORT=8002 app.js

Clusters

From the Node.js Documentation:

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

Using cluster allows you to take advantage of this feature by forking a process of your app.js for each CPU detected. However, the cluster module is still in experimental stage, it is a solution but I usually prefers the first one. Anyway it's good understanding its purpose and behavior. A good approach is to have a separated js file for launch your app in cluster mode that is entirely optional and app.js is not tied in any way to it. And can look like this:

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

// Setup the cluster to use app.js
cluster.setupMaster({
  exec: 'app.js'
});

// Monitor dying workers
cluster.on('exit', function(worker) {
  console.log('Worker ' + worker.id + ' died');
  cluster.fork();
});

// Fork a worker for each available CPU
for (var i = 0; i < os.cpus().length; i++) {
  cluster.fork();
}

This cluster example is taken from this great (hackathon starter boilerplate)[https://github.com/sahat/hackathon-starter] by Sahat.

In both cases you could use any session storages like Connect-Mongo, Connect-Redis or any other session storage.