nodejs实现多进程(cluster 模式)

2021-06-07  本文已影响0人  miao8862

Nodejs的主进程是单线程的,但它有多线程处理方案(更准备来说是多进程方案),即主进程开启不同的子进程,主进程接收所有请求,然后将分发给其它不同的nodejs子进程处理。

它一般有两种实现:

  1. 主进程监听一个端口,子进程不监听端口,通过主进程分发请求到子进程;
  2. 主进程和子进程分别监听不同端口,通过主进程分发请求到子进程。

cluster模式

Nodejscluster模式用的就是第一种实现,它使用一个主线程master和多个子线程worker,形成一个集群,通过主线程来向子线程分发请求。cluster 实现了对 child_process 的封装,通过 fork 方法创建子进程的方式实现了多进程模型。

cluster的使用

httpclusterprocess都是nodejs的内置模块,不需要额外安装

  1. 创建一个http服务
// http是nodejs内置模块
const http = require('http')

const server = http.createServer((req, res) => {
  res.write('hello http!')
  res.end()
})

server.listen(3030, () => {
  console.log('server is listening on http://localhost:3030')
})

// process是node的进程模块,可以从这个模块获取进程的信息,以及控制进程的
console.log(`worker ${process.pid} start`)
  1. 创建cluster
    在下面程序中,会首先判断有没有主进程,如果没有,就创建进程,它会默认第一个进程为主进程
const cluster = require('cluster')
// 开启的子进程数
const workerNum = 3;
// 如果是主进程
if(cluster.isMaster) {
  // 创建子进程
  for(let i = 0; i < workerNum; i++) {
    // 通过cluster.fork创建子进程
    cluster.fork()
  }
// 如果有子进程,就启动相关服务,这里会使用三个进程来执行http服务演示
}else {
  require('./http-server')
}
image.png

实现过程大概是这样的: cluster 模块应用 child_process 来创建子进程,子进程通过复写掉 cluster._getServer 方法,从而在 server.listen 来保证只有主进程监听端口,主子进程通过 IPC进行通信,其次主进程根据平台或者协议不同,应用两种不同模块(round_robin_handle.jsshared_handle.js)进行请求分发给子进程处理。

PM2

PM2是后台进程管理器,是多进程方案的一个成熟应用,可以帮助管理和保持应用程序在线。

基本使用

全局安装:npm install pm2@latest -g
它的使用也非常简单:

image.png

负载均衡:

PM2对nodejs应用,可以根据系统自动实现负载均衡:pm2 start http-server.js -i max

image.png

PM2配置

我们肯定不想每次启动时,都要手动输入一堆指令,所以我们可以将这些配置统一使用配置文件来管理,注意js文件名必须是 xxx.config.js,我这里用ecosystem.config.js
apps数组中,可以放置多个对象,对应多个文件执行不同的配置

// ecosystem.config.js
module.exports = {
  apps : [{
    name: "http-server", // 启动进程名
    script: "./src/http-server.js", // 启动文件
    instances: 4, // 启动进程数
    exec_mode: 'cluster', // 多进程多实例
    // 设置不同环境的环境配置
    // 开发环境,对应--env 后的参数
    env_development: {
      NODE_ENV: "dev",
      watch: true, // 开发环境使用 true,其他设置为 false
    },
    // 测试环境
    env_testing: {
      NODE_ENV: "test",
      watch: false, // 开发环境使用 true,其他设置为 false
    },
    // 生产环境
    env_production: {
      NODE_ENV: "prod",
      watch: false, // 开发环境使用 true,其他必须设置为 false
    },
    // 日志日期格式
    log_date_format: 'YYYY-MM-DD HH:mm Z',
    // 错误日志文件,必须设置在项目外的目录,这里为了测试
    error_file: '~/Desktop/logs/err.log', 
    //  流水日志,包括 console.log 日志,必须设置在项目外的目录,这里为了测试
    out_file: '~/Desktop/logs/info.log', 
    // 最大重启数据,当应用被认定连续n次不稳定重启起,再重启
    max_restarts: 10,
  },{
    name: "express-test", // 启动进程名
    script: "./src/express-test.js", // 启动文件
    instances: 4, // 启动进程数
    exec_mode: 'cluster', // 多进程多实例
  }]
}

执行配置:pm2 start ecosystem.config.js --env dev

可以看到在启动后,桌面上生成了流水和错误日志:


日志
流水日志

参考:
Node Process模块 API:http://nodejs.cn/api/process.html
pm2官网: https://pm2.keymetrics.io/docs/usage/pm2-doc-single-page/

上一篇下一篇

猜你喜欢

热点阅读