MST
星途 面试题库

面试题:Node.js集群模式下的错误处理与高可用性设计

在Node.js的集群模式(cluster module)下,如何设计一个健壮的错误处理机制,确保即使某个工作进程出现未捕获的异常,整个应用程序仍然能够保持高可用性?请详细描述你的设计思路,包括进程间通信、错误检测、恢复策略等方面。
46.5万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试

1. 进程间通信

  • 使用 process.send()message 事件:在工作进程中,当捕获到未捕获的异常时,通过 process.send() 向主进程发送包含错误信息的消息。例如:
process.on('uncaughtException', (err) => {
    process.send({
        type: 'error',
        error: err
    });
    // 这里可以选择是否立即关闭工作进程
});

在主进程中,通过监听 message 事件来接收这些错误信息:

worker.on('message', (msg) => {
    if (msg.type === 'error') {
        // 处理错误
    }
});

2. 错误检测

  • 工作进程检测:在每个工作进程中,使用 process.on('uncaughtException') 捕获未捕获的异常,这可以检测到同步代码以及异步回调中抛出的异常。
  • 主进程检测:主进程除了通过 message 事件接收工作进程传来的错误,还可以使用 worker.on('exit') 事件来检测工作进程意外退出的情况。例如:
worker.on('exit', (code, signal) => {
    if (code!== 0 &&!isGracefulExit) {
        // 工作进程异常退出,进行相应处理
    }
});

3. 恢复策略

  • 重启工作进程:当主进程接收到工作进程的错误消息或者检测到工作进程异常退出时,主进程可以选择重启该工作进程。例如:
const cluster = require('cluster');
if (cluster.isMaster) {
    const worker = cluster.fork();
    worker.on('message', (msg) => {
        if (msg.type === 'error') {
            console.error('Worker reported an error:', msg.error);
            worker.kill();
            const newWorker = cluster.fork();
        }
    });
    worker.on('exit', (code, signal) => {
        if (code!== 0 &&!isGracefulExit) {
            console.error('Worker exited abnormally. Restarting...');
            const newWorker = cluster.fork();
        }
    });
}
  • 负载均衡调整:在重启工作进程的同时,可以暂时调整负载均衡策略,减少对刚出现错误的工作进程(即将重启)的请求分配。例如,使用 cluster.schedulingPolicy = cluster.SCHED_NONE 暂时禁用该工作进程的请求分配,直到重启完成。然后再将调度策略恢复为正常,如 cluster.schedulingPolicy = cluster.SCHED_RR
  • 记录错误日志:无论是工作进程还是主进程,在处理错误时都应该记录详细的错误日志,包括错误堆栈信息、发生时间等,以便后续分析问题。可以使用 console.error() 或者专业的日志库如 winston 来记录日志。例如:
const winston = require('winston');
const logger = winston.createLogger({
    level: 'error',
    format: winston.format.json(),
    transports: [
        new winston.transport.Console()
    ]
});
process.on('uncaughtException', (err) => {
    logger.error('Uncaught Exception in worker:', err.message, err.stack);
    process.send({
        type: 'error',
        error: err
    });
});