关于egg框架的多进程模型

548 阅读3分钟

1、egg框架—多进程模型

JavaScript 代码是运行在单线程上的,一个Node.js进程只运行在一个CPU上,这样就会导致一些缺陷。

  1. 无法享受现代计算机的多核计算优势。
  2. 如果有代码错误,导致Node服务异常的时候,无法稳定的提供服务。

基于以上问题,egg 使用了 node 的 Cluster 模块,它会在运行的时候,启动多个进程。

2、Cluster是什么

  1. 在服务器上启动多个进程。

  2. 每一个进程都跑的是同一份源代码。

  3. 这些进程可以同时监听一个端口。

其中:

  1. 负责启动其他进程的叫做 Master 进程,他好比是一个 “包工头” ,不做具体工作,只负责启动其他进程。

  2. 其他被启动的叫 Worker 进程,顾名思义就是干活的 “工人” ,他们接收请求,对外提供服务。

  3. Worker进程的数量一般根据服务器的CPU数量决定,这样可以完美利用多核资源。

import cluster from 'node:cluster';
import http from 'node:http';
import { cpus } from 'node:os';
import process from 'node:process';

const numCPUs = cpus().length;

if (cluster.isPrimary) {
  console.log(`Primary ${process.pid} is running`);

  // 衍生工作进程。
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`worker ${worker.process.pid} died`);
  });
} else {
  // 工作进程可以共享任何 TCP 连接
  // 在本示例中,其是 HTTP 服务器
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('hello world\n');
  }).listen(8000);

  console.log(`Worker ${process.pid} started`);
}

3、egg框架—进程守护

Node.js 进程在一些特殊的情况下,进程会自动退出,而进程退出的时候,我们为了保障Node.js的服务可用性,应该重启 node 服务,这个过程叫进程守护。

Node.js 进程退出可以分为两类:

第一类、未捕获的异常

这种情况下,Node提供了 process.on('uncaughtException', handler) 这样的api,实现了额外的异常捕获。

在handler中,我们需要 Master 重新 fork 一个新的 Worker 进程。

第二类、OOM、系统异常

OOM:OutOfMemory,表示内存溢出。

经常是由于内存泄露引起的问题。内存泄露如何发生?——node的内存泄露

4、egg框架—Agent 机制

对外提供的服务,基于稳定性、性能等方面的考虑,我们需要多个 Worker 的工作模式。

但是对内的一些工作,如果使用多个 Workder,就会出现问题。比如生成log文件,基本上不可能每一个 Worker 都生成一次,这是资源的浪费。

egg在考虑上述问题的时候,专门让一个单独的进程处理这些事情,这个单独的进程叫Agent Worker。

image2022-5-10_17-14-33.png

5、egg框架—Agent 和 Worker的区别

1、从功能层面:Agent主要用于处理对内的一些公共服务。比如:log日志的生成、只需要执行一次的公共型事务等。

Worker主要用于对外的请求处理。

2、从实现层面:Agent主要是通过node的一个api来实现的——child_process.fork

Worker的实现主要从另一个api来实现——cluster.fork

6、Egg多进程 && pm2多进程

1、egg的多进程,是基于 Master — Agent — Worker 的模型,运行node服务,比较适合当下的企业级node服务场景。

2、pm2的多进程,没有Agent的说法,在真实的业务场景中,有些事物不需要多个进程同时来做。