Simple Node Cluster
After much testing of our internal API, we made it available for several sites to use & got terrible performance.
Of course, we got better performance with Node than we did with PHP, thanks to async
parallelizing functions, but we didn’t think too much about Node’s
single-threaded nature.
We already had several sites using the API with more being added daily, all causing performance to quickly dwindle.
In a rush, we discovered Node’s cluster
module, which I don’t remember from v0.6
, but is pretty reliable in v0.10
.
Per the cluster
documentation:
A single instance of Node runs in a single thread. To take advantage of multicore systems the user will sometimes want to launch a cluster of Node processes to handle the load.
The cluster module allows you to easily create child processes that all share server ports.
Implementation was dead easy.
1. Set up our Express application for easy use via require
:
// app/server.js
var app = require('./app')
var http = require('http')
http.createServer(app).listen(app.get('port'), function () {
console.log('Express server listening on port ' + app.get('port'))
})
For development, we will run node app/server
:
$ node app/server.js
Express server listening on port 3000
2. Create cluster.js
// app/cluster.js
var cluster = require('cluster')
if (cluster.isMaster) {
// Count the machine's CPUs
var cpuCount = require('os').cpus().length
// Create a worker for each CPU
for (var i = 0; i < cpuCount; i += 1) {
cluster.fork()
}
// Listen for dying workers & start 'em back up!
cluster.on('exit', function () {
cluster.fork()
})
} else {
require('./server')
}
3. Update package.json
to use cluster.js
// package.json
{
"scripts": {
"start": "node app/cluster"
}
}
4. Done!
Now on production, npm start
will run node app/cluster
and spawn up 4+ instances:
$ npm start
> api@1.4.2 start /Users/deploy/api
> node app/cluster
Express server listening on port 3000
Express server listening on port 3000
Express server listening on port 3000