nodejs-多进程

1,074 阅读1分钟

为啥需要多进程

nodejs中javascript是运行在单线程上的,无法充分榨干多核系统资源,并行的处理更多的用户请求。

nodejs中的多进程使用

依赖cluster模块

const cluster = require('cluster');
const http = require('http');
const os = require('os');


const cpus = os.cpus().length;

// console.log(cluster);

if(cluster.isMaster) {
    console.log('Master process run at pid: %d', process.pid);
    for(let i = 0; i<cpus; i++) {
        // 内部基于child_process.fork()实现
        // child_process.fork()默认的
        cluster.fork();
        cluster.on('exit', (worker, code, signal)=> {
            console.log(`worker ${worker.process.pid} died`);
        })
    }
} else {
    http.createServer(function (req,res) {
        res.writeHead(200);
        res.end(`worker run pid: ${process.pid} , say hello world`);
    }).listen(8000);
    console.log(`Worker ${process.pid} started`);
}

cluster(集群)

cluster依赖child_process.fork实现,理解成自动的多次运行我们的脚本

node index.js
node index.js
node index.js
....

所以,同一份代码文件中,我们通过cluster.isMaster 或者 cluster.isPrimary(cluster.isMaster 在源代码中被标记为Deprecated)来区分当前代码是执行在fork的进程中还是主进程中

cluster源码

// 根据env 引用对应的模块
const childOrPrimary = 'NODE_UNIQUE_ID' in process.env ? 'child' : 'primary';
module.exports = require(`internal/cluster/${childOrPrimary}`);

所以上面的代码

// 会根据环境变量,也就是根据是否是fork执行,来确认引入哪个模块
const cluster = require('cluster');
...

primary模块

cluster.fork = function(env) {
  // id 初始值 0
  const id = ++ids;
  // 创建worker进程
  const workerProcess = createWorkerProcess(id, env);
  const worker = new Worker({
    id: id,
    process: workerProcess
  });
}

createWorkerProcess方法

function createWorkerProcess(id, env) {
    ...
    // 调用了child_process.fork方法
    return fork(cluster.settings.exec, cluster.settings.args, {
        cwd: cluster.settings.cwd,
        env: workerEnv,
        serialization: cluster.settings.serialization,
        silent: cluster.settings.silent,
        windowsHide: cluster.settings.windowsHide,
        execArgv: execArgv,
        stdio: cluster.settings.stdio,
        gid: cluster.settings.gid,
        uid: cluster.settings.uid
      });
}

child模块

cluster.isWorker = true;
cluster.isMaster = false; // Deprecated alias. Must be same as isPrimary.
cluster.isPrimary = false;
...