• 不用 pm2 怎么守护进程


    自上一篇 pm2 部署介绍 后,有面试官问道不用 pm2 做进程守护,该怎么办?

    由于 NodeJs 是单线程执行的,所以主线程抛出了一个错误就会退出程序。线上部署当然不可能出了异常就退出了,所以需要守护进程。

    node-forever

    使用 forever start simple-server.js

    精髓在forever-monitor

    其原理就是崩溃就重启一个。

    Monitor.prototype.start = function (restart) {
      var self = this,
          child;
      
      // 非重启则返回自身进程
      if (this.running && !restart) {
        process.nextTick(function () {
          self.emit('error', new Error('Cannot start process that is already running.'));
        });
        return this;
      }
      
      // 重启标志传入时,重新 fork 进程,方法里使用了 child_process.spawn 执行命令来衍生一个新进程
      child = this.trySpawn();
      if (!child) {
        process.nextTick(function () {
          self.emit('error', new Error('Target script does not exist: ' + self.args[0]));
        });
        return this;
      }
    
      this.ctime = Date.now();
      this.child = child;
      this.running = true;
      this.isMaster = cluster.isMaster;
    
      process.nextTick(function () {
        self.emit(restart ? 'restart' : 'start', self, self.data);
      });
    
      function onMessage(msg) {
        self.emit('message', msg);
      }
    
      // Re-emit messages from the child process
      this.child.on('message', onMessage);
    
      // 监听退出事件,崩溃时退出也算。
      child.on('exit', function (code, signal) {
        var spinning = Date.now() - self.ctime < self.minUptime;
        child.removeListener('message', onMessage);
        self.emit('exit:code', code, signal);
    
        function letChildDie() {
          self.running = false;
          self.forceStop = false;
          self.emit('exit', self, spinning);
        }
    
        function restartChild() {
          self.forceRestart = false;
          process.nextTick(function () {
            self.start(true);
          });
        }
    
        self.times++;
        
        // 强制关闭,当重启次数过多
        if (self.forceStop || (self.times >= self.max && !self.forceRestart)
          || (spinning && typeof self.spinSleepTime !== 'number') && !self.forceRestart) {
          letChildDie();
        }
        // 按照最小的重启时间间隔,防止不停崩溃重启
        else if (spinning) {
          setTimeout(restartChild, self.spinSleepTime);
        }
        else {
          restartChild();
        }
      });
      
      // 返回重启后的新进程
      return this;
    };
    

    shell 脚本启动守护 node

    实例

    WEB_DIR='/var/www/ourjs'
    WEB_APP='svr/ourjs.js'
    
    #location of node you want to use
    NODE_EXE=/root/local/bin/node
    
    while true; do
        {
            $NODE_EXE $WEB_DIR/$WEB_APP config.magazine.js
            echo "Stopped unexpected, restarting 
    
    "
        } 2>> $WEB_DIR/error.log
        sleep 1
    done
    

    这个文件非常简单,只有启动的选项,守护的核心功能是由一个无限循环 while true; 来实现的,为了防止过于密集的错误阻塞进程,每次错误后间隔1秒重启服务。错误日志记录也非常简单,直接将此进程控制台当中的错误输出到error.log文件即可: 2>> $WEB_DIR/error.log 这一行, 2 代表 Error。

    cluster API

    Node 原生提供了 cluster,可以创建共享服务器端口的子进程。就如 EggJS 官网多进程模型的说明

    +---------+                 +---------+
    |  Worker |                 |  Master |
    +---------+                 +----+----+
         | uncaughtException         |
         +------------+              |
         |            |              |                   +---------+
         | <----------+              |                   |  Worker |
         |                           |                   +----+----+
         |        disconnect         |   fork a new worker    |
         +-------------------------> + ---------------------> |
         |         wait...           |                        |
         |          exit             |                        |
         +-------------------------> |                        |
         |                           |                        |
        die                          |                        |
                                     |                        |
                                     |                        |
    

    可以再业务代码之上起一个 master 进程,他 fork 出多个 worker 进程来处理任务,每当一个 worker 挂了,会有事件传回给 master,master 就能重新 fork 一份新的 worker。

    那么只要 master 不挂,就能达到守护进程的目的。

  • 相关阅读:
    【BZOJ1067】【SCOI2007】降雨量(线段树)
    【BZOJ3489】A simple rmq problem(树套树)
    【BZOJ1146】【CTSC2008】网络管理
    【BZOJ3236】【Ahoi2013】作业
    计算几何的一些板
    【BZOJ3173】【Tjoi2013】最长上升子序列(树状数组)
    解决phpmyadmin导入长脚本超时
    make报错make: *** [sapi/cli/php] Error 1
    wampserver配置redis在phpinfo()里面找不到
    阿里云服务器安装Apache环境外网不能访问
  • 原文地址:https://www.cnblogs.com/everlose/p/12840151.html
Copyright © 2020-2023  润新知