web前端 - nodejs中的cluster模块

181 阅读3分钟

cluster模块

cluster概述

cluster模块是对process的封装,

  • 使用该模块可以创建共享同一个端口的子进程。
  • 实现子进程之间的负载均衡机制。

集群中的主进程称为Master, fork出的子进程成为Worker

api

nodejs.org/dist/latest…

cluster.fork

创建一个worker进程,返回一个Worker实例。

const worker = cluster.fork()

console.log(worker.process.pid)  //打印子进程pid

cluster.workers

在primary(master)进程里调用,获取所有worker进程对应的Worker实例。

// 打印所有worker的状态
for (const worker of Object.values(cluster.workers)) {
  console.log(`worker-${worker.id}|${worker.process.pid}|${worker.status}`);
}

官方文档里提到了一个有意思的点,一个worker会在触发disconnect和exit事件后,从workers集合里删除,但这2个事件本身发生的先后是不保证的。

cluser.isMaster/cluser.isPrimary/cluster.isWorker

这几个api用于判断当前进程上主进程还是fork出的worker进程。

  • cluser.isMaster判断当前进程是否是主进程,若process.env.NODE_UNIQUE_ID为undefied,则为true。
  • cluser.isPrimary功能和cluser.isMastery一致
  • cluser.isWorker判断当前进程是否是worker进程

cluster.setupMaster/cluster.setupPrimary

// fork出的子进程运行worker.js, args是传递给进程的参数
cluster.setupPrimary({
  exec: 'worker.js',
  args: ['--use', 'https'],
  silent: true,
});

cluster.on

cluster.on('disconnect', (worker) => {
   // worker断开链接
});

cluster.on('exit', (worker) => {
   // worker进程退出
});

cluster.on('fork', (worker) => {
  //  新的worker进程被fork
});

cluster.on('listening', (worker) => {
  // 新worker开始监听端口
});

cluster.on('message', (worker) => {
  // 接受到来自worker消息
});

cluster.on('online', (worker) => {
  // worker进程开始运行后,在fork事件之后
});

cluster.on('setup', () => {
 // cluster.setupPrimary被调用
});

cluster多进程模型

生产环境多进程模型

clutser.drawio.png

这个模型解决了什么问题

  • js只有一个主线程,无法充分利用的多核cpu的资源,通过cluster可以实现多进程模型
  • 多个进程监需要监听多个端口,通过cluster创建多子进程和主进程可以共享同一个端口(主进程监听,通过进程通信转发给子进程)

子进程创建

使用cluster.fork创建一个worker进程,cluster.workers可以获取所有的woker进程。

端口监听

master进程创建socket,与端口绑定, 子进程的listen方法实际上上被hack了的。

负载均衡策略

可以通过改变cluster.schedulingPolicy的值设置采用的负载均衡策略,这部分简单介绍rr策略(时片轮转法)。

round-robin 时间片轮转法

默认采用的策略是 round-robin 时间片轮转法, 该算法是把请求依次分配个每个用户,从序号1 ~ 序号Max,然后再进入新的循环。(这本身是一个进程调度算法,将一个较小时间单元定义为时间量或时间片。时间片的大小通常为 10~100ms,没有一个会占有CPU超过一个时间片,除非它是唯一可执行的进程。)

worker1 process1 pid=1 
worker2 process2 pid=2
worker3 process2 pid=3

主进程会分别把很小时间内的所有请求转发worker进程, 其顺序为worker1-worker2-worker3,然后再从worker1开始。

这个策略默认所有用户的处理能力是相同的,所以如果各个用户的性能存在差异,会出现负载不均衡的情况。

weight-round-robin 加权轮转法

在时片轮转法的基础上给每个用户分配不同的权重,来调整每个用户被分配次数占总数的比例,以应对每个用户处理能力不同的实际场景。

process1 pid=1 weight=1
process2 pid=2 weight=1
process2 pid=3 weight=98

当分配次数非常大时,进程123被分配到的次数占总数比例分别趋近1%, 1%, 98%。

pm2

一个node应用的进程管理器,内置负载均衡等功能。 生产部署node应用时,因为nodejs是单线程,一台机器上通常需要跑拉起进程来一利用计算资源。

Pm2解决的问题:

1.拉起和管理多个应用进程,并管理它们的状态,让你的程序在生产环境始终保持活跃状态。
2.负载均衡,主进程接受请求,通过IPC方式转发给子进程处理。