Multicore Programming in Node.js
An explanation of how to use Node.js to take advantage of multicore CPUs with the Cluster API.
Join the DZone community and get the full member experience.
Join For FreeNode.js is a single-threaded platform; if you want to take advantage of multicore CPUs, you need to fork multiple processes. This is called “clustering,” and is supported by the Node.js Cluster API. In this article you will see how the cluster module works.
The cluster module helps you to spawn new processes on the operating system. Each process works independently, so you cannot use shared state between child processes.
Each process communicates with the main process by IPC and pass server handles back and forth.
Cluster supports two types of load distribution:
- The main process listens on a port, accepts new connection and assigns it to a child process in a round robin fashion.
- The main process assigns the port to a child process and child process itself listen the port.
How Do You Use It?
We begin with creating the node project folder; and initialize it using npm.
$ mkdir clstr && cd clstr && npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help json` for definitive documentation on these fields
and exactly what they do.
Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
name: (clstr)
version: (1.0.0)
description:
entry point: (index.js) app.js
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to d:\DEV\workspaces\learn\dzone\clstr\package.json:
{
"name": "clstr",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
Is this ok? (yes)
Next step is to add the express framework to our project.
$npm install express --save
Project configuration is completed. Now we will create a simple express application that handles an HTTP-GET request.
$edit app.js
module.exports = function(cluster){
var express = require('express')
var app = express()
app.get('/',function(req, res){
console.log('Worker %d started!'+new Date(), cluster.worker.id);
for(var i = 0; i < 999999999; i++) {}
res.end('Hello from Worker ' + cluster.worker.id);
console.log('Worker %d returned!'+new Date(), cluster.worker.id);
});
app.listen(8080,function(){
console.log('Application started! Worker %d started!, process %d', cluster.worker.id, cluster.worker.process.pid);
});
}
At line 6 simulating a heavy task that makes the CPU busy, so if another request comes, it will be assigned to another child process.
Next we will create our cluster application that manages multiple workers.
$edit cluster.js
var cluster = require('cluster');
var app = require('./app');
cluster.schedulingPolicy = cluster.SCHED_RR;
if(cluster.isMaster){
var cpuCount = require('os').cpus().length;
for (var i = 0; i < cpuCount; i += 1) {
cluster.fork();
}
}else{
app(cluster);
}
cluster.on('fork', function(worker) {
console.log('forked -> Worker %d', worker.id);
});
At line 4 we set cluster schedulingPolicy to round-robin; if you want to rely on the operating system you can use cluster.SCHED_NONE. At line 5 checking if the current process is the main process, if so get the number of CPUs your machine has, and fork new child process for each CPU. Cluster will run the cluster.js as forking a new child process. As the “cluster.js” run for a child process at line 5 “cluster.isMaster” will return false, and application will be created for the child process which is a hello world express app.
Action time, let’s start our clustered application and see how it works.
$node cluster.js
forked -> Worker 1
forked -> Worker 2
forked -> Worker 3
forked -> Worker 4
forked -> Worker 5
forked -> Worker 6
forked -> Worker 7
forked -> Worker 8
Application started! Worker 2 started!, process 13716
Application started! Worker 4 started!, process 2444
Application started! Worker 5 started!, process 12656
Application started! Worker 6 started!, process 6276
Application started! Worker 3 started!, process 12044
Application started! Worker 8 started!, process 1100
Application started! Worker 1 started!, process 14756
Application started! Worker 7 started!, process 12268
I have opened 8 command windows and invoked localhost:8080/ in each, here is the result.
And the server log is as follows:
Opinions expressed by DZone contributors are their own.
Comments