Chapter 4: Cluster Module and Load Balancing
Chapter 4 of 15
Chapter 4: Cluster Module and Load Balancing
4.1 Clustering
The cluster module allows you to create child processes that share server ports, enabling you to take advantage of multi-core systems.
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isPrimary) {
console.log(`Master ${process.pid} is running`);
// Fork workers
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} died`);
cluster.fork(); // Restart worker
});
} else {
// Workers can share TCP connection
http.createServer((req, res) => {
res.writeHead(200);
res.end(`Process ${process.pid} handled request
');
}).listen(8000);
console.log(`Worker ${process.pid} started`);
}
4.2 Load Balancing Strategies
Node.js cluster module uses round-robin by default on Windows, and uses the operating system's load balancing on Unix systems.
// Custom load balancing
const cluster = require('cluster');
const workers = {};
if (cluster.isPrimary) {
// Create workers
for (let i = 0; i < numCPUs; i++) {
const worker = cluster.fork();
workers[worker.id] = { requests: 0, worker };
}
// Custom distribution logic
function getWorker() {
// Find worker with least requests
let minRequests = Infinity;
let selectedWorker = null;
for (const id in workers) {
if (workers[id].requests < minRequests) {
minRequests = workers[id].requests;
selectedWorker = workers[id].worker;
}
}
return selectedWorker;
}
}
4.3 Worker Communication
// Master to worker
if (cluster.isPrimary) {
const worker = cluster.fork();
worker.send({ message: 'Hello from master' });
worker.on('message', (msg) => {
console.log('Message from worker:', msg);
});
} else {
process.on('message', (msg) => {
console.log('Message from master:', msg);
process.send({ response: 'Hello from worker' });
});
}
4.4 Process Management
// Graceful shutdown
if (cluster.isPrimary) {
process.on('SIGTERM', () => {
console.log('Master received SIGTERM');
for (const id in cluster.workers) {
cluster.workers[id].kill();
}
});
} else {
process.on('SIGTERM', () => {
server.close(() => {
console.log('Worker shutting down gracefully');
process.exit(0);
});
});
}