Node JS Cluster Module With Web Server Example

Node JS app executes in a single thread. But if your machine has multiple CPU cores, it can also use multiple CPU cores with it’s cluster module. This can improve hardware usage efficiency. So you can make your Node JS app more scalable.

1. Node JS Web Server Cluster Example.

  1. In this example, we will create an http web server in Node JS.
  2. The web server has one cluster master process and two worker processes.
  3. When the app starts, the master process will create and initialize the two worker process.
  4. And when an http request comes to the web server, the cluster master process will pick a free worker process ( in round-robin order )  to process the request.

1.1 Install Node JS Cluster Module.

  1. But first, you should make sure the Node JS cluster module has been installed.
  2. Open a terminal and execute the command npm list like below.
    sh-3.2# npm list cluster -g
    /usr/local/lib
    └── (empty)
  3. If the result in step one is empty, then run npm install to install it. We install the Node JS cluster module globally, commonly it is installed in the /usr/local/lib/node_modules directory.
    sh-3.2# npm install cluster -g
    + [email protected]
    

1.2 Node JS Cluster Module Methods.

  1. isMaster: This attribute is used to check whether the current process is a cluster master process or not.
  2. fork(): This method is used to fork a master child process.

1.3 Web Server Cluster Source Code.

  1. Save the below code in a file cluster_example.js. Open a terminal and run the below js file. You can see the console print out cluster’s master and worker process id.
  2. When browsing URL http://localhost:8000 from Google Chrome or Firefox, you can see different worker-process processes different browser-request from the web page message.
    browse-http-web-server-in-cluster-from-firefox-google-chrome
  3. But when you execute the below code, you will find Google Chrome request will be executed twice when browsing the same url once.
  4. This is because, for one url request ( such as http://localhost:8000), google chrome will generate two url requests (http://localhost:8000, http://localhost:8000/favicon.ico).
  5. So we should filter out the /favicon.ico request in source code, this issue does not exist in Firefox and other browsers.
    // Include http, and cluster module.
    var http = require('http');
    var cluster = require('cluster');
    // There are totally 2 cpu in machine.
    var cpu_numbers = 2;
    
    // Create a http web server object.
    var server = http.createServer(function (req, res) {
    
        /* For google chrome, one url request will generate two request, one for "/favicon.ico" the other for "/".
           So to avoid the second request in one url request, we should filter out the favicon.ico request. */
        if(req.url!='/favicon.ico') {
            res.writeHead(200, {'Content-Type': 'text/plain'});
            res.end('Hello World from worker process ' + process.pid);
            console.log('Process request worker pid is ' + process.pid);
        }
    })
    
    // When app start.
    if (cluster.isMaster) {
        // Print out the master pid.
        console.log('Master process id ' + process.pid)
        // Create worker process in cluster.
        for (var i = 0; i < cpu_numbers; i++) {
            // Invoke cluster fork method to create a cluster worker.
            var worker = cluster.fork();
            // Print out the worker pid.
            console.log('Worker ' + (i + 1) + ' process id ' + worker.process.pid);
        }
    } else {
        // Make http web server listen on port 8000.
        server.listen(8000);
    }
  6. Below is the console output.
    /usr/local/bin/node /Users/zhaosong/Documents/WorkSpace/dev2qa.com-example-code/JavaScriptExampleWorkspace/NodeJSWorkspace/ClusterExample/cluster_example.js
    Master process id 7555
    Worker 1 process id 7556
    Worker 2 process id 7557
    Process request worker pid is 7556
    Process request worker pid is 7557

2. Make Node JS Cluster Work Continuously.

  1. There is an issue in this example. When a worker process is stopped, the cluster will only have one worker process. When all the worker process stops, the cluster will fail.
  2. To avoid this issue, the Node JS cluster module provides ‘online‘ and ‘exit‘ events.
  3. The two events will be triggered when a child worker process is created or stopped. So we can create a new worker when the exit event is happen. Thus the cluster will have enough workers to process client http request even when one worker stops.
  4. So add the below code in cluster_example.js.
    // When app start.
    if (cluster.isMaster) {
        // Print out the master pid.
        console.log('Master process id ' + process.pid)
        ......
    
        cluster.on('online', function(worker){
           console.log('A new worker is online, worker process id is ' + worker.process.pid)
        });
    
        cluster.on('exit', function(worker, code, signal) {
            console.log('Worker ' + worker.process.pid + ' exit, status code is ' + code + ', and signal is ' + signal);
            console.log('A new worker will be started.');
            cluster.fork();
        });
    }
  5. Now run the example again. You can see below console output.
    /usr/local/bin/node /Users/zhaosong/Documents/WorkSpace/dev2qa.com-example-code/JavaScriptExampleWorkspace/NodeJSWorkspace/ClusterExample/cluster_example.js
    Master process id 7690
    Worker 1 process id 7691
    Worker 2 process id 7692
    A new worker is online, worker process id is 7691
    A new worker is online, worker process id is 7692
  6. Run the below command to kill worker process which process id is 7691 in the terminal.
    # kill 7691
  7. You will see below console output which means the exit and online events are all triggered, and a new worker is created after one worker exit.
    Worker 7691 exit, status code is null, and signal is SIGTERM
    A new worker will be started.
    A new worker is online, worker process id is 7698

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.