你自己写的进程,你得管理

在互联网后端服务场景下,我们会面对如何在进程挂掉的时候(例如爆CPU或者内存导致进程卡死),你的服务能不间断地提供服务,提供系统稳定性的问题。无论你的服务器是单机的还是跑在集群上,都需要思考在实际过程中如何做到这一点。而基于多任务操作系统的异步性特征(不可复现),我们需要回归到对服务进程进行管理和监控。

下面我讲一下怎么去做进程管理。

守护进程

脱离终端的控制,默默在操作系统背后跑的进程,就是守护进程(后台进程)。

不同操作系统用的技术是不一样的,Linux以前是init.d,后面转用Systemd去做进程管理,因为Linux有不同的发行分支,所以某些特殊的发行版会有一丢丢区别。

像nodejs还有pm2和forever等工具去做这类事情

其他还有如Supervisor

守护进程Wiki:https://zh.wikipedia.org/wiki/%E5%AE%88%E6%8A%A4%E8%BF%9B%E7%A8%8B

Linux守护进程的启动方法:https://www.ruanyifeng.com/blog/2016/02/linux-daemon.html

Systemd 入门教程:https://www.ruanyifeng.com/blog/2016/03/systemd-tutorial-commands.html

中断信号

顺带要提一下中断信号,什么是中断信号呢?

摘抄下Wiki的关键名词描述,如下:

中断是用以提高计算机工作效率、增强计算机功能的一项重要技术。
最初引入硬件中断,只是出于性能上的考量。
后来被用于CPU外部与内部紧急事件的处理、机器故障的处理、时间控制等多个方面,并产生通过软件方式进入中断处理(软中断)的概念。

通俗点讲,就是先有硬件中断,然后后面引入了软中断,都是为了进程抢占计算资源去处理某些事件。

而信号(signal),则是一种软中断,信号机制是进程间通信的一种方式,采用异步通信方式。在终端,可通过kill -l查看所有的signal信号。

中断信号WIKI:https://zh.wikipedia.org/wiki/%E4%B8%AD%E6%96%B7

Linux的中断信号:http://gityuan.com/2015/12/20/signal/

PM2

PM2是一个Nodejs写的进程管理工具。

我有看到其他一些PM2源码分析的文章写得很不错,也有助于我去看源码,但包版本不是最新的,也不会差很多,大同小异。我看的包版本是5.1.2

PM2 的功能、插件非常的丰富,但比较核心的功能其实不多:

  1. 多进程管理
  2. 系统信息监控
  3. 日志管理

PM2的执行方式(exec_mode)有forkcluster两种

  • fork mode是通过child_process package的spawn去开新进程
  • cluster mode是通过cluster package的fork去开子进程

nodejs中spawnfork的区别是啥?

SpawnFork
通过命令行去开启新的进程在原有进程上去开子进程

后面打算读完源码有时间再写一篇详细的文章再介绍

pm2源码分析:https://juejin.cn/post/6866081343454773262

pm2的信号流:https://pm2.keymetrics.io/docs/usage/signals-clean-restart/

代码控制优雅重启

Nodejs

Nodejs有cluster模块可以去创建多进程,pm2的cluster mode也是基于cluster模块的。
一个最简单的实现优雅重启的例子

import * as cluster from 'cluster';
import { cpus } from 'os';
import * as process from 'process';

const numCPUs = cpus().length;

if (cluster.isMaster) {
    console.log(`Master ${process.pid} is running`);
    // Fork workers.
    for (let i = 0; i < numCPUs; i++) {
      cluster.fork();
    }

    cluster.on('exit', (worker, code, signal) => {
      // 进程中断信号,这里就会有上面说的软中断信号
      // 这里可以加入进程中断后应该重启进程或者其他操作,优雅重启的处理地方
      if (signal) {
        console.log(`worker was killed by signal: ${signal}`);
      } else if (code !== 0) {
        console.log(`worker exited with error code: ${code}`);
      } else {
        console.log(`worker ${worker.process.pid} died`);
      }
    });
  } else {
    // Workers can share any TCP connection
    // 程序入口
    // bootstrap()
    console.log(`Worker ${process.pid} started`);
  }

什么情况下会用到?例如,为了确保Http服务器能提供不间断的服务,防止一个进程短路导致服务器不可用,可以开多进程去控制重启出问题的进程,从而通过自修复达到服务不间断。

另外,我们在任何情况下,都应该监听进程的系统中断信号,做一下容错处理或者监控处理,一般进程如下。

process.on('exit', (code) => {
  console.log('Process exit event with code: ', code);
});

像上面使用了cluster模块则是使用cluster.on('exit', (worker, code, signal) => {...})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值