Skip to content

node的原生cluster模块 #56

Description

@Wscats

主进程和子进程

constcluster=require('cluster');if(cluster.isMaster){console.log('这是主进程');cluster.fork();cluster.fork();}elseif(cluster.isWorker){console.log(`这是工作进程 #${cluster.worker.id}`);}
  • 在主进程中 cluster 表示主进程(用于监听、发送事件), process 是本身的进程,worker 表示子进程,通过 cluster.workers 获取
  • 在子进程中 process 表示子进程(用于监听、发送事件),也可以通过 cluster.worker 表示当前子进程
    cluster.worker.process 等价于 process(在子进程中)
constcluster=require('cluster');consthttp=require('http');console.log(cluster.isMaster);// 这里如果我电脑是八核,则会打印一个true,七个false// 一个主进程 判断是否主进程if(cluster.isMaster){// 跟踪 http 请求。letnumReqs=0;setInterval(()=>{console.log(`请求的数量 = ${numReqs}`);},1000);// 对请求计数。functionmessageHandler(msg){if(msg.cmd&&msg.cmd==='notifyRequest'){numReqs+=1;}}// 启动 worker 并监听包含 notifyRequest 的消息。// 循环查找电脑核心,分配进程constnumCPUs=require('os').cpus().length;for(leti=0;i<numCPUs;i++){// 生成多个工作进程(子进程)cluster.fork();}for(constidincluster.workers){// 监听工作进程发过来的信息cluster.workers[id].on('message',messageHandler);}// 多个工作进程}else{// 工作进程有一个 http 服务器。http.Server((req,res)=>{res.writeHead(200);res.end('你好世界\n');// 通知主进程接收到了请求。process.send({cmd: 'notifyRequest'});}).listen(8000);}

屏幕快照 2019-09-09 上午8 36 28

  • cluster 用于监听 process(child) 子进程触发的各种事件
  • worker 在主进程中获取,用于和自身通信。当子进程触发事件时,会返回当前的 worker 以及相关的信息到主进程相应的事件中
  • process(parent) 主进程本身的进程实例,在通信过程中基本没有用到
  • process(child) 子进程本身的实例,只能在子进程获取用于监听自身的事件

可见主进程与子进程通过这样一个三角关系互相通信,其中 cluster 和 worker 是在主进程中获取的,process(child) 是子进程。 cluster 通过操作 worker 通知子进程,子进程本身和 cluster 进行通信。为什么要这样设计呢?因为子进程会有多个,只有通过 worker 才能选择和哪个进程通信。

遍历所有子进程

for(constidincluster.workers){callback(cluster.workers[id]);}

通信

主进程全局监听来自子进程的信息

// 全局监听cluster.on('message',(worker,msg)=>{console.log(msg)})// 遍历所有子进程监听for(constidincluster.workers){// 监听工作进程发过来的信息cluster.workers[id].on('message',messageHandler);}

子进程主动触发事件,与主进程通信

process.send({cmd: 'notifyRequest',msg: 'hi'},()=>{console.log('send')});

主进程主动和子进程通信

constcluster=require('cluster');if(cluster.isMaster){constworker=cluster.fork();setInterval(()=>{worker.send('你好');},1000)}elseif(cluster.isWorker){process.on('message',(msg)=>{console.log(msg)process.send(msg);});}

伪造多请求

可以使用多个子进程发送数据,伪造请求:

constcluster=require('cluster');consthttp=require('http');constnumCPUs=require('os').cpus().length;if(cluster.isMaster){console.log(`主进程 ${process.pid} 正在运行`);// 衍生工作进程。for(leti=0;i<numCPUs;i++){cluster.fork();}cluster.on('exit',(worker,code,signal)=>{console.log(`工作进程 ${worker.process.pid} 已退出`);});}else{// 工作进程可以共享任何 TCP 连接。// 在本例子中,共享的是 HTTP 请求。http.get('http://www.baidu.com/',(res)=>{console.log(res.statusCode)})console.log(`工作进程 ${process.pid} 已启动`);}

参考文档

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions