API

The Cluster API at its core is extremely simple, all we need to do is pass our tcp or http server to cluster(), then call listen() as we would on the http.Server itself.

 var cluster = require('../')
   , http = require('http');

 var server = http.createServer(function(req, res){
   res.writeHead(200);
   res.end('Hello World');
 });

 cluster(server)
   .listen(3000);

Alternatively (and recommended) is to export your server instance via module.exports, and supply a path to cluster(). For example app.js:

 module.exports = http.createServer(....);

and server.js with our cluster logic, allowing our server to be require()ed within tests, and preventing potential issues by having open database connections etc within the master processes, as only the workers need access to the server instance.

cluster('app')
  .listen(3000);

A good example if this, is a long-lived database connection. Our app.js may have this initialized at the top, which although will work fine stand-alone, may cause cluster’s master processes to hang when restarting or closing due to the connection remaining active in the event loop.

 var db = redis.createClient();

Plugins

A plugin simple a function that accepts the master process. Most plugin functions return another anonymous function, allowing them to accept options, for example:

function myPlugin(path){
  return function(master) {
    // do stuff
  }
}

To use them, all we need to do is pass it to the use() method:

cluster(server)
  .use(myPlugin('/some/path'))
  .listen(3000);

To use a plugin that is bundled with Cluster simply grab it from the cluster object:

 cluster(server)
   .use(cluster.logger())
   .listen(3000);

Settings

Below are the settings available:

We can take what we have now, and go on to apply settings using the set(option, value) method. For example:

cluster(server)
  .set('working directory', '/')
  .set('workers', 5)
  .listen(3000);

Signals

Cluster performs the following actions when handling signals:

Events

The following events are emitted, useful for plugins or general purpose logging etc.

Master#state

Current state of the master process, one of:

Master#isWorker

true when the script is executed as a worker.

  cluster = cluster(server).listen(3000);

  if (cluster.isWorker) {
    // do something
  }

Alternatively we can use the CLUSTER_WORKER env var, populated with the worker’s id.

Master#isMaster

true when the script is executed as master.

 cluster = cluster(server).listen(3000);

 if (cluster.isMaster) {
   // do something
 }

Master#set(option, value)

Set option to value.

Master#use(plugin)

Register a plugin for use.

Master#in(env)

Conditionally perform the following action, if NODE_ENV matches env.

 cluster(server)
   .in('development').use(cluster.debug())
   .in('development').listen(3000)
   .in('production').listen(80);

The environment conditionals may be applied to several calls:

 cluster(server)
   .set('working directory', '/')
   .in('development')
     .set('workers', 1)
     .use(cluster.logger('logs', 'debug'))
     .use(cluster.debug())
     .listen(3000)
   .in('production')
     .set('workers', 4)
     .use(cluster.logger())
     .use(cluster.pidfiles())
     .listen(80);

If we perform the same action for environments, set them before the first in() call, or use in('all').

cluster(server)
  .set('working directory', '/')
  .do(function(){
    console.log('some arbitrary action');
  })
  .in('development')
    .set('workers', 1)
    .use(cluster.logger('logs', 'debug'))
    .use(cluster.debug())
  .in('production')
    .set('workers', 4)
    .use(cluster.logger())
    .use(cluster.pidfiles())
  .in('all')
    .listen(80);

Master#spawn(n)

Spawn n additional workers.

Master#close()

Graceful shutdown, waits for all workers to reply before exiting.

Master#destroy()

Hard shutdown, immediately kill all workers.

Master#restart([signal])

Defaults to a graceful restart, spawning a new master process, and sending SIGQUIT to the previous master process. Alternatively a custom signal may be passed.

Master#kill([signal])

Sends SIGTERM or signal to all worker processes. This method is used by Master#restart(), Master#close() etc.