Nodejs写自己的守护进程 防止进程死掉

Nodejs写自己的守护进程 防止进程死掉

起初我也是使用网上流行的forever来尝试,发现控制forever挺麻烦的,特别是多个nodejs节点的时候,总是提示.forever文件已经存在,需要使用-a或者–append来处理,然后实际上有时候进程死了它并不知晓

后来就写了个简单的守护进程,用主进程来启动子进程,如果子进程死了就重启子进程,还有优化的余地,比如如何停止所有的节点的问题,这个用别的shell来处理了,这里只是贴出守护进程的代码

也说说写这个守护进程的目的,起来正常来说,如果容错写的够好是不需要守护进程的,但是我之前发现有个问题,mysql在运行一定时间之后,会断开所有的连接,导致nodejs读取mysql的连接中断,这时候nodejs就会挂掉,使用连接池连接mysql的话,虽然nodejs不会挂掉,但是连接池实际上属于无用状态,也读取不到mysql的数据,导致请求会阻塞,浏览器一直无法响应

var spawn = require('child_process').spawn,
    server = null;

function startServer(){ console.log(‘start server’); server = spawn(‘node’,[‘app.js’]); console.log('node js pid is '+server.pid); server.on(‘close’,function(code,signal){ server.kill(signal); server = startServer(); }); server.on(‘error’,function(code,signal){ server.kill(signal); server = startServer(); }); return server; };

startServer();


2 回复

Nodejs写自己的守护进程 防止进程死掉

起初我也是使用网上流行的forever来尝试,发现控制forever挺麻烦的,特别是多个nodejs节点的时候,总是提示.forever文件已经存在,需要使用-a或者--append来处理,然后实际上有时候进程死了它并不知晓。

后来就写了个简单的守护进程,用主进程来启动子进程,如果子进程死了就重启子进程。这样可以确保即使进程意外退出也能自动重启,保证服务的高可用性。当然,还可以进一步优化,比如如何停止所有的节点的问题,这个用别的shell脚本来处理,这里只是贴出守护进程的代码。

写这个守护进程的目的

一般来说,如果程序的容错机制写得足够好,是不需要守护进程的。但是我在实践中遇到一个问题:MySQL在运行一定时间之后,会断开所有的连接,导致Node.js读取MySQL的连接中断,这时Node.js就会挂掉。使用连接池连接MySQL的话,虽然Node.js不会挂掉,但是连接池实际上处于无用状态,无法读取到MySQL的数据,导致请求会阻塞,浏览器一直无法响应。

示例代码

var spawn = require('child_process').spawn;

let server = null;

function startServer() {
    console.log('Starting server...');
    server = spawn('node', ['app.js']);
    console.log('Node.js PID is ' + server.pid);

    server.on('close', (code, signal) => {
        console.error(`Server process exited with code ${code} and signal ${signal}`);
        server = startServer();
    });

    server.on('error', (err) => {
        console.error(`Error occurred: ${err.message}`);
        server = startServer();
    });

    return server;
}

startServer();

代码解析

  1. 引入child_process模块:我们使用child_process.spawn()方法来启动子进程。
  2. 定义startServer函数:这个函数负责启动子进程,并监听其关闭和错误事件。
  3. 监听close事件:当子进程关闭时,会触发close事件。在这里,我们重新启动子进程。
  4. 监听error事件:当子进程发生错误时,也会触发error事件。同样,我们会重新启动子进程。
  5. 启动服务器:最后,调用startServer()来启动第一个子进程。

通过这种方式,我们可以确保即使子进程意外退出或发生错误,守护进程也会自动重启子进程,从而保持服务的稳定性和可用性。


为了防止 Node.js 进程意外终止,可以编写一个简单的守护进程。这个守护进程将负责启动子进程,并在子进程异常退出时重启它。这样可以确保应用持续运行,即使遇到某些错误或意外情况。

下面是一个简单的守护进程实现示例:

const { spawn } = require('child_process');

let childProcess;

function startChildProcess() {
    console.log('Starting child process...');
    childProcess = spawn('node', ['app.js']);

    childProcess.on('exit', (code, signal) => {
        console.log(`Child process exited with code ${code} and signal ${signal}`);
        startChildProcess(); // 在子进程退出后重新启动它
    });

    childProcess.on('error', (err) => {
        console.error(`Error in child process: ${err.message}`);
        startChildProcess(); // 在发生错误时重新启动子进程
    });
}

startChildProcess();

解释:

  1. 使用 spawn 方法来启动一个新的 Node.js 进程(子进程),并传入你想执行的脚本路径。
  2. 监听子进程的 exiterror 事件。
    • 当子进程退出时,exit 事件会被触发,你可以在这里重新启动子进程。
    • 当子进程发生错误时,error 事件会被触发,同样地,在这里也可以重新启动子进程。

注意事项:

  • 上述代码仅简单地实现了子进程退出后自动重启的功能。如果你需要更复杂的管理逻辑(如停止所有子进程、定时重启等),可能需要进一步扩展。
  • 在生产环境中,建议结合其他工具(如 PM2)一起使用,它们提供了更多高级功能,如负载均衡、日志管理和监控等。

这种简单的守护进程模式可以确保你的应用在意外终止后能够快速恢复,但它并不能解决根本性的错误或性能问题。

回到顶部