阿里云主机折上折
  • 微信号
Current Site:Index > The cluster module translates this sentence into English, outputting plain text directly without any additional content.

The cluster module translates this sentence into English, outputting plain text directly without any additional content.

Author:Chuan Chen 阅读数:1493人阅读 分类: Node.js

The cluster module in Node.js allows developers to leverage the capabilities of multi-core CPUs by creating child processes (workers) to handle tasks in parallel. It follows a master-slave model, where the master process manages the child processes, and the child processes share the same port and handle requests independently, significantly improving server throughput and reliability.

Core Concepts of the cluster Module

The core of the cluster module lies in the division of labor between the master process and the worker processes. The master process does not handle business logic directly but is responsible for scheduling and managing the workers, while the worker processes are the units that execute the actual code. Here’s a minimal example:

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

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

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

  cluster.on('exit', (worker, code, signal) => {
    console.log(`Worker process ${worker.process.pid} has exited`);
  });
} else {
  // Worker processes can share any TCP connection
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('Hello World\n');
  }).listen(8000);

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

Inter-Process Communication (IPC)

Although worker processes run independently, the cluster module provides an IPC mechanism. The master and worker processes can exchange data using process.send() and the message event. For example:

// Master process code
cluster.on('fork', (worker) => {
  worker.send({ type: 'greeting', msg: 'Hello from master' });
});

// Worker process code
process.on('message', (msg) => {
  if (msg.type === 'greeting') {
    console.log(`Worker ${process.pid} received: ${msg.msg}`);
  }
});

Load Balancing Strategies

By default, the cluster module uses a round-robin strategy to distribute requests (except on Windows). Node.js allows modifying this strategy via cluster.schedulingPolicy:

const cluster = require('cluster');
cluster.schedulingPolicy = cluster.SCHED_RR; // Round-Robin
// Or
cluster.schedulingPolicy = cluster.SCHED_NONE; // Let the OS decide

Practical Use Cases

HTTP Server Clustering

When building high-concurrency HTTP services, cluster effectively prevents single-process blocking:

const cluster = require('cluster');
const http = require('http');

if (cluster.isMaster) {
  const cpuCount = require('os').cpus().length;
  for (let i = 0; i < cpuCount; i++) {
    cluster.fork();
  }
} else {
  http.createServer((req, res) => {
    // Simulate CPU-intensive task
    let count = 0;
    for (let i = 0; i < 1e7; i++) { count++ }
    
    res.end(`Worker ${process.pid} handled request`);
  }).listen(3000);
}

Zero-Downtime Restarts

By handling signals and managing processes, you can achieve seamless restarts:

// Master process
process.on('SIGUSR2', () => {
  const workers = Object.values(cluster.workers);
  
  const restartWorker = (i) => {
    if (i >= workers.length) return;
    const worker = workers[i];
    worker.on('exit', () => {
      if (!worker.exitedAfterDisconnect) return;
      const newWorker = cluster.fork();
      newWorker.on('listening', () => restartWorker(i + 1));
    });
    worker.disconnect();
  };
  
  restartWorker(0);
});

Advanced Features and Considerations

Shared Port Mechanism

All worker processes share the same port via the net module's IPC channel, with connections distributed by the master process's round-robin handler. This differs from using the child_process module directly, where each child process would need to bind to a different port.

State Sharing Issues

Due to memory isolation between workers, avoid directly modifying global state. Solutions include:

  • Using external storage like Redis
  • Coordinating state through the master process
  • Adopting a stateless design
// Bad example: Independent counters in workers
let requestCount = 0;

http.createServer((req, res) => {
  requestCount++;
  res.end(`Total requests: ${requestCount}`); // Each worker has its own count
}).listen(8080);

Error Handling Best Practices

Always listen for worker exceptions; uncaught errors will cause the process to exit:

cluster.on('exit', (worker, code, signal) => {
  console.error(`Worker ${worker.process.pid} died`);
  if (!worker.exitedAfterDisconnect) {
    cluster.fork(); // Auto-restart
  }
});

// In worker processes
process.on('uncaughtException', (err) => {
  console.error('Caught exception:', err);
  process.exit(1); // Exit proactively for master to restart
});

Performance Optimization Tips

Controlling the Number of Processes

While workers are typically created per CPU core, I/O-intensive scenarios may benefit from more:

const totalWorkers = require('os').cpus().length * (isIOIntensive ? 1.5 : 1);

Sticky Sessions

For scenarios requiring session persistence (e.g., WebSocket), use packages like sticky-session:

const sticky = require('sticky-session');
const server = http.createServer((req, res) => { /* ... */ });

sticky.listen(server, 3000, {
  workers: 4,
  env: { NODE_ENV: 'production' }
});

Comparison with Tools Like PM2

While process managers like PM2 also offer clustering, the cluster module has advantages:

  • No additional dependencies
  • Finer control over logic
  • Deep integration with the Node.js runtime

Typical PM2 cluster configuration:

pm2 start app.js -i max  # Automatically starts a cluster based on CPU cores

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

上一篇:child_process模块

下一篇:进程间通信

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.