Introduction

Node.js is single-threaded by design, which means it can handle only one operation at a time. However, modern applications often require handling multiple tasks simultaneously to improve performance and scalability. The Cluster module in Node.js allows you to create child processes (workers) that share the same server port, enabling you to take full advantage of multi-core systems.

Key Concepts

  1. Master Process: The main process that spawns worker processes.
  2. Worker Processes: Child processes that handle incoming requests.
  3. IPC (Inter-Process Communication): Mechanism for communication between the master and worker processes.

How It Works

  1. Master Process: The master process is responsible for spawning and managing worker processes.
  2. Worker Processes: Each worker process runs an instance of the Node.js server and handles incoming requests.
  3. Load Balancing: The master process distributes incoming requests among the worker processes to balance the load.

Practical Example

Step 1: Setting Up the Master Process

Create a file named cluster-master.js:

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  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`);
  });
} else {
  // Workers can share any TCP connection
  // In this case, it is an HTTP server
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('Hello World\n');
  }).listen(8000);

  console.log(`Worker ${process.pid} started`);
}

Explanation

  • Master Process: Checks if the current process is the master using cluster.isMaster.
    • Forks worker processes equal to the number of CPU cores.
    • Listens for the 'exit' event to log when a worker dies.
  • Worker Process: If the current process is not the master, it creates an HTTP server that listens on port 8000.

Step 2: Running the Cluster

Run the script using Node.js:

node cluster-master.js

You should see output indicating that the master process and multiple worker processes have started.

Step 3: Testing the Cluster

Open a web browser or use a tool like curl to make requests to http://localhost:8000. You should see "Hello World" as the response. The requests will be handled by different worker processes, demonstrating load balancing.

Practical Exercise

Exercise: Implement a Clustered Server with Logging

  1. Modify the worker process to log the process ID and request URL.
  2. Ensure that each worker logs its start and end time for each request.

Solution

const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  console.log(`Master ${process.pid} is running`);

  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`Worker ${worker.process.pid} died`);
  });
} else {
  http.createServer((req, res) => {
    const start = Date.now();
    console.log(`Worker ${process.pid} handling request for ${req.url}`);
    
    res.writeHead(200);
    res.end('Hello World\n');
    
    const end = Date.now();
    console.log(`Worker ${process.pid} finished request for ${req.url} in ${end - start}ms`);
  }).listen(8000);

  console.log(`Worker ${process.pid} started`);
}

Explanation

  • Logging: Added logging to the worker process to log the process ID and request URL.
  • Timing: Logged the start and end time for each request to measure the handling time.

Common Mistakes and Tips

  • Not Handling Worker Crashes: Always handle the 'exit' event to restart crashed workers.
  • Overloading a Single Worker: Ensure proper load balancing by distributing requests evenly among workers.
  • Resource Sharing: Be cautious when sharing resources between workers to avoid conflicts.

Conclusion

The Cluster module in Node.js is a powerful tool for improving the performance and scalability of your applications by leveraging multi-core systems. By understanding and implementing the concepts of master and worker processes, you can efficiently handle multiple tasks simultaneously. In the next topic, we will explore Worker Threads, another method for parallel execution in Node.js.

Node.js Course

Module 1: Introduction to Node.js

Module 2: Core Concepts

Module 3: File System and I/O

Module 4: HTTP and Web Servers

Module 5: NPM and Package Management

Module 6: Express.js Framework

Module 7: Databases and ORMs

Module 8: Authentication and Authorization

Module 9: Testing and Debugging

Module 10: Advanced Topics

Module 11: Deployment and DevOps

Module 12: Real-World Projects

© Copyright 2024. All rights reserved