NodeJS High Availability

Do you have a NodeJS application serving production traffic? Ever wonder how Yahoo might handle this? If yes, at some point or other you must have thought it would be nice to have a clean and simple solution for high availability.

Read below for a detailed overview of how you can achieve this just like we did here at Yahoo.

What modules are needed?

How does it work?

Use monitr to start monitoring when your application gets loaded with this simple statement monitor.start() and stop monitoring with monitor.stop() when your application shuts down.

The monitr module creates a thread and starts monitoring the application. It looks for process status from various system files and reports the status on a socket.

The process-watcher module provides a listener on this socket. This listener is also responsible for sending a SIGHUP and SIGKILL if the process did not honor the performance boundaries given to the watcher.

How do we add it to an existing/new node app?

MONITOR

// Your includes

var monitor = require(‘monitr’);
monitor.start();

// Your application logic

process.on(‘exit’, function () {
    monitor.stop();
});

LISTENER


var watcher = require('process-watcher');

/*
 * Dummy metric monitoring object.
 */
var watcher_metric = {
    increment : function (name, v) {
    },
    set : function (name, v) {
    }
};

var dgpath = '/tmp/nodejs.mon',
    statusPath = '/tmp/watcher_status_path_test',
    watcher_config = {
	    max_inactive : 0.001,
	    monitor : 0.001,
	    monPath: dgpath,
	    timeout : 3,
	    timeout_start : 60
    };

//Instantiate watcher
var watcher_instance = new watcher.Watcher({
    metric: watcher_metric,
    config : watcher_config
});

In this ecosystem, how do we view application behavior?

The mod_statuspage module provides a simple middleware to view each process status on the specified server.


//Your includes
var app = express();

app.use(status({
        url: '/status',
        check: function(req) {
            if (req.something == false) {
                return false;
            }
            return true;
        },
        responseContentType : 'html'
    }));

//Other middleware
app.use(...
//URLs served
app.get(...

Putting it all together …

Source

Example application and listener

Running it

Run your application and watcher on separate terminals

node ./application.js node ./listener.js

Status page

Once you have your application and the watcher running, you can view your application status at http://localhost:8000/status

image

Test URL to trigger watcher to kill the worker process

http://localhost:8000/late-response

You can see from the application that the URL ‘late-response’ deliberately engages CPU for 5 seconds. The watcher is configured to kill the worker processes that are idle more than 3 seconds.

Hence hitting this URL above will cause the watcher to send a SIGHUP to the worker process that took the request.

Console Output (on a 2 core box)
Starting worker 0
Starting worker 1
Worker 23107 online
Worker 23108 online
Go to: http://127.0.0.1:8000/status
Go to: http://127.0.0.1:8000/status
                   >>>> Access URL http://localhost:8000/late-response
worker 23107 died
Worker 23114 online
Go to: http://127.0.0.1:8000/status

Make sure you check out all of our other NodeJS modules on our Github page, they are all used in production here at Yahoo.