MST

星途 面试题库

面试题:JavaScript 优化 Node HTTP 服务器并发处理之集群模块应用

Node.js 的集群(cluster)模块可以利用多核 CPU 来提高服务器的并发处理能力。请详细说明如何使用 cluster 模块来优化 Node HTTP 服务器的并发性能。包括如何创建工作进程、如何在主进程和工作进程间分配请求,以及在使用过程中可能会遇到哪些问题及解决方案。
43.8万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

创建工作进程

  1. 引入 cluster 模块: 在 Node.js 应用程序中,首先需要引入 cluster 模块。
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
  1. 主进程创建工作进程: 在主进程中,使用 cluster.fork() 方法来创建工作进程。通常会根据 CPU 的核心数来创建相应数量的工作进程。
if (cluster.isMaster) {
    console.log(`主进程 ${process.pid} 正在运行`);
    for (let i = 0; i < numCPUs; i++) {
        cluster.fork();
    }
    cluster.on('exit', (worker, code, signal) => {
        console.log(`工作进程 ${worker.process.pid} 已退出`);
        cluster.fork();
    });
} else {
    // 工作进程逻辑
}

主进程和工作进程间分配请求

  1. 主进程监听端口: 主进程监听指定的端口,然后将接收到的请求分发给工作进程。在 Node.js 中,主进程可以使用 cluster.isMaster 标识来处理这部分逻辑。
if (cluster.isMaster) {
    const server = http.createServer((req, res) => {
        // 这里主进程不处理请求,只是负责分发
    });
    server.listen(3000, () => {
        console.log('服务器已启动,监听端口 3000');
    });
}
  1. 工作进程处理请求: 工作进程通过 cluster.isWorker 标识来识别自身,并处理接收到的请求。工作进程可以像普通的 Node.js HTTP 服务器一样处理请求。
if (cluster.isWorker) {
    const server = http.createServer((req, res) => {
        res.writeHead(200, { 'Content-Type': 'text/plain' });
        res.end('你好,这是工作进程 ' + process.pid + ' 的响应\n');
    });
    server.listen();
}

Node.js 的 cluster 模块会自动将请求负载均衡到各个工作进程上,默认使用的是循环调度(Round - Robin)算法。

使用过程中可能遇到的问题及解决方案

  1. 共享资源问题
    • 问题:工作进程之间是独立的,它们不能直接共享内存等资源。如果需要共享某些数据(如数据库连接池),可能会导致资源重复创建或者数据不一致的问题。
    • 解决方案:可以使用外部存储(如 Redis)来共享数据,工作进程通过操作外部存储来实现数据的共享。另外,对于一些资源(如数据库连接池),可以在主进程中创建,然后通过进程间通信(IPC)将连接传递给工作进程。
  2. 进程间通信问题
    • 问题:在主进程和工作进程之间传递复杂数据结构时,可能会遇到序列化和反序列化的问题,并且不正确的通信可能导致数据丢失或进程崩溃。
    • 解决方案:使用 worker.send()process.on('message', callback) 进行进程间通信时,确保传递的数据是可序列化的(如 JSON 格式)。同时,在接收端进行必要的数据验证,以防止异常数据导致进程崩溃。
  3. 错误处理问题
    • 问题:工作进程中的未捕获异常可能导致整个工作进程崩溃,影响服务器的稳定性。
    • 解决方案:在工作进程中,使用 process.on('uncaughtException', callback) 捕获未处理的异常,进行适当的错误处理,如记录日志、重启工作进程等。在主进程中,通过监听 cluster.on('exit', callback) 事件,当工作进程因为异常退出时,可以及时重启该工作进程。