主进程和子进程
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);}
- 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} 已启动`);}参考文档
主进程和子进程
cluster.worker.process 等价于 process(在子进程中)
可见主进程与子进程通过这样一个三角关系互相通信,其中 cluster 和 worker 是在主进程中获取的,process(child) 是子进程。 cluster 通过操作 worker 通知子进程,子进程本身和 cluster 进行通信。为什么要这样设计呢?因为子进程会有多个,只有通过 worker 才能选择和哪个进程通信。
遍历所有子进程
通信
主进程全局监听来自子进程的信息
子进程主动触发事件,与主进程通信
主进程主动和子进程通信
伪造多请求
可以使用多个子进程发送数据,伪造请求:
参考文档