Skip to content

Instantly share code, notes, and snippets.

@bennadel
Created March 7, 2017 13:48
Hello World: Concurrency In Node.js Using The Cluster Module
// Require the core node modules.
var chalk = require( "chalk" );
var cluster = require( "cluster" );
var os = require( "os" );
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
// The cluster module in Node.js works by executing the application entry-point
// multiple and sharing the master ports with the worker ports. As such, this code
// needs to distinguish between the Master process and the forked Worker process(es).
if ( cluster.isMaster ) {
console.log( chalk.red( "[Cluster]" ), "Master process is now running.", process.pid );
// Since each Node.js process executes in a single thread, we want to create
// Workers based on the number of Cores available on the operating system. This
// way, we don't get Workers competing with each other for resources.
for ( var i = 0, coreCount = os.cpus().length ; i < coreCount ; i++ ) {
var worker = cluster.fork();
}
// When one of the Workers dies, the cluster will emit an "exit" event, which
// we can use to then spawn new Worker processes.
cluster.on(
"exit",
function handleExit( worker, code, signal ) {
console.log( chalk.yellow( "[Cluster]" ), "Worker has died.", worker.process.pid );
console.log( chalk.yellow( "[Cluster]" ), "Death was suicide:", worker.exitedAfterDisconnect );
// If a Worker was terminated accidentally (such as by an uncaught
// exception), then we can try to restart it.
if ( ! worker.exitedAfterDisconnect ) {
var worker = cluster.fork();
// CAUTION: If the Worker dies immediately, perhaps due to a bug in the
// code, you can run [from what I have READ] into rapid CPU consumption
// as Master continually tries to create new Workers.
}
}
);
} else {
// Any time we deal with concurrency, we want to separate out the concurrency code
// from the rest of the code. As such, we don't want to actually define out Worker
// logic here. Instead, we want to require it from a different module. This has the
// happy side-effect of allowing us to run the application in Cluster mode or in
// stand-alone mode by using different entry points (cluster.js vs. server.js).
require( "./server" );
console.log( chalk.red( "[Worker]" ), "Worker has started.", process.pid );
}
// Require the core node modules.
var http = require( "http" );
// ----------------------------------------------------------------------------------- //
// ----------------------------------------------------------------------------------- //
// Here, our Worker is running in a completely isolated V8 process - it doesn't share
// memory with the Cluster or with other Workers. The one notable exception is that it
// is allowed to the share PORTS with the Cluster. As such, each Worker will share
// port 8000 with the Cluster. Or, if this module was run as the application's entry
// point, it will just use port 8000 the same way it would without Clustering.
http
.createServer(
function handleRequest( request, response ) {
response.writeHead(
200,
{
"Content-Type": "text/html"
}
);
response.write( "Hello world from process " + process.pid + "." );
// In order to actually get the Cluster to distribute requests via the
// default Round Robin algorithm - FOR THE DEMO - I have to hold the
// request open so that I can generate concurrent requests to the Cluster.
setTimeout( response.end.bind( response ), 300 );
}
)
.listen( 8000 )
;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment