The node cluster

Node now comes with its own completely rewritten cluster module. Cluster allows node to start multiple processes behind the cluster frontend and monitors and manages them. We will take a quick look at how to make an application cluster with this module, but note that this is only for creating multiple processes and we must still set up a tool to monitor the cluster master and also a proxy to forward requests to the node server.

Let us see how we can use the cluster module. The best part about the cluster module is you don't need to actually change your application. Cluster will run a master instance, and we can start multiple instances of our application and they will all listen to a shared port.

Here is the script that we can use for clustering the app.js file:

var cluster = require('cluster'),

if (cluster.isMaster) {
  var noOfWorkers =
           process.env.NODE_WORKERS || require('os').cpus().length;
  while(workers.length < noOfWorkers) {
    cluster.fork();
  }
} else {
  require('./app.js'),
}

So, what's happening here? The first thing we do is use require on the cluster module. In the next line, we are checking whether the instance that is started is the master process or the worker.

If it is the master process, we check if the NODE_WORKERS environment variable is set, else we get the number of processors available on the system our server is running on. To set the NODE_WORKERS environment variable, you can run the following:

$ export NODE_WORKERS=2

The previous command will tell the cluster to start two nodes.

Now, in the loop, we call fork on the cluster. This calls child_process.fork so that the master and the started workers can communicate via IPC.

When the cluster process is run from fork, cluster.isMaster is false and so our app.js script is in the current worker process.

In our application, when we call server.listen(3000), the worker serializes this and sends over the request to the server, the server checks if it already is listening on that port, and returns the handle for the listener, if it is present. Else, the server starts listening on the port and passes on the handle to the newly created listener.

Since all our workers request to listen on port 3000, the server will start listening on the port when the first worker starts and will pass on the same handler to all the workers. When a request comes in, it will be handled by any worker that can take it up and process it.

Since our monitoring tool (Monit or Forever, or others) will now be monitoring only the master process, it becomes the master's responsibility to monitor the workers. This means that the cluster should restart any worker that happens to die. We will do this, by adding the following event handler in the master process:

cluster.on('exit', function (worker, code, signal){
  var exitCode = worker.process.exitCode;
  console.log('worker ' + worker.process.pid +
                               ' died ('+exitCode+'). restarting...'),
  cluster.workers[worker.id].delete();
  cluster.fork();
});

Monitoring of the process is done by listening to the exit event on the socket. This is the event that will be triggered when any worker dies. The event handler will get the worker, its exit code, and the signal that caused the process to be killed. In the handler, we log the death and we start a new worker process using cluster.fork().

Now we can start the new clustered application; we'll run cluster.js instead of app.js. So change the start script in package.json to run cluster.js:

 "scripts": {
    "start": "node cluster",
  }

And then run the application with npm.

npm start

This will start the application and everything will look just as it was. But when you start using it, you'll notice that there are errors while trying to connect to a room, or while sending messages. These errors are because we are using an in-memory store for our Express.js sessions and socket.io uses an in-memory store to store and transfer all the messages.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset