美文网首页
nodejs实现多进程(cluster 模式)

nodejs实现多进程(cluster 模式)

作者: miao8862 | 来源:发表于2021-06-07 00:29 被阅读0次

    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
      在下面程序中,会首先判断有没有主进程,如果没有,就创建进程,它会默认第一个进程为主进程
    • 在源码中,是调用cluster.fork()方法时,会执行setupPrimary方法创建主进程,它会使用initialized标识是否为true会判断是否为首次创建,如果是就创建主进程,否则就跳过
    • 使用createWorkerProcess来创建子进程,这个方法实际是使用child_process来创建子进程的
    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
    它的使用也非常简单:

    • 开启(http-server.js是要启动的程序):pm2 start http-server.js
    • 重启(程序):restart app_name
    • 重载(配置和程序):reload app_name
    • 停止:pm2 stop app_name
    • 删除:pm2 delete app_name
    • 监听模式:pm2 start xx.js --watch
    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/

    相关文章

      网友评论

          本文标题:nodejs实现多进程(cluster 模式)

          本文链接:https://www.haomeiwen.com/subject/cosqjltx.html