Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NodeJS on multiple processors (PM2, Cluster, Recluster, Naught)

Tags:

node.js

pm2

I am investigating options for running node in a multi-core environment.

I'm trying to determine the best approach and so far I've seen these options

  • Use built in cluster library to spin up works and respond to signals
  • Use PM but, PM2 -i is listed as beta.
  • Naught
  • Recluster

Are there other alternatives? What are folks using in production?

like image 330
Douglas Ferguson Avatar asked Feb 19 '15 06:02

Douglas Ferguson


People also ask

Is it possible to cluster multiple node processes?

When process isolation is not needed, use the worker_threads module instead, which allows running multiple application threads within a single Node. js instance. The cluster module allows easy creation of child processes that all share server ports.

Does PM2 use cluster?

exec_mode: "cluster" tells PM2 to use the Node. js cluster module to execute the code. instances:0 when this is set to 0, PM2 will automatically spawn a number of child processes that are equal to the available number of cores.

How does Nodejs cluster work?

The Node. js Cluster module enables the creation of child processes (workers) that run simultaneously and share the same server port. Each spawned child has its own event loop, memory, and V8 instance. The child processes use IPC (Inter-process communication) to communicate with the parent Node.

What is cluster mode in Nodejs?

Definition and Usage. The cluster module provides a way of creating child processes that runs simultaneously and share the same server port.


1 Answers

I've been using the default cluster library, and it works very well. I've had over 10,000 concurrents(multiple clusters on multiple servers) and it works very well.

It is suggested to use clusters with domain for error handling.

This is lifted straight from http://nodejs.org/api/domain.html I've mades some changes on how it spawns new clusters for each core of your machine. and got rid of if/else and added express.

var cluster = require('cluster'),
    http = require('http'),
    PORT = process.env.PORT || 1337,
    os = require('os'),
    server;

function forkClusters () {
    var cpuCount = os.cpus().length;
    // Create a worker for each CPU
    for (var i = 0; i < cpuCount ; i += 1) {
        cluster.fork();
    }
}

// Master Process
if (cluster.isMaster) {

    // You can also of course get a bit fancier about logging, and
    // implement whatever custom logic you need to prevent DoS
    // attacks and other bad behavior.
    //
    // See the options in the cluster documentation.
    //
    // The important thing is that the master does very little,
    // increasing our resilience to unexpected errors.

    forkClusters ()

    cluster.on('disconnect', function(worker) {
        console.error('disconnect!');
        cluster.fork();
    });

}
function handleError (d) {
    d.on('error', function(er) {
        console.error('error', er.stack);

        // Note: we're in dangerous territory!
        // By definition, something unexpected occurred,
        // which we probably didn't want.
        // Anything can happen now!Be very careful!

        try {
            // make sure we close down within 30 seconds
            var killtimer = setTimeout(function() {
                process.exit(1);
            }, 30000);
            // But don't keep the process open just for that!
            killtimer.unref();

            // stop taking new requests.
            server.close();

            // Let the master know we're dead.This will trigger a
            // 'disconnect' in the cluster master, and then it will fork
            // a new worker.
            cluster.worker.disconnect();
        } catch (er2) {
            // oh well, not much we can do at this point.
            console.error('Error sending 500!', er2.stack);
        }
    });
}
// child Process
if (cluster.isWorker) {
    // the worker
    //
    // This is where we put our bugs!

    var domain = require('domain');
    var express = require('express');
    var app = express();
    app.set('port', PORT);

    // See the cluster documentation for more details about using
    // worker processes to serve requests.How it works, caveats, etc.

    var d = domain.create();
    handleError(d);

    // Now run the handler function in the domain.
    //
    // put all code here. any code included outside of domain.run will not handle errors on the domain level, but will crash the app.
    //

    d.run(function() {
        // this is where we start our server
        server = http.createServer(app).listen(app.get('port'), function () {
            console.log('Cluster %s listening on port %s', cluster.worker.id, app.get('port'));
        });
    });
}
like image 85
Brian Noah Avatar answered Oct 02 '22 03:10

Brian Noah