Advanced Node.js

Master advanced Node.js concepts including microservices, performance optimization, and production deployment.

advanced Backend Development 7 hours

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);
        });
    });
}