You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
constcluster=require('cluster');consthttp=require('http');constnumCPUs=require('os').cpus().length;if(cluster.isMaster){masterProcess();}else{childProcess();}functionmasterProcess(){console.log(`Master ${process.pid} is running`);for(leti=0;i<numCPUs;i++){console.log(`Forking process number ${i}...`);cluster.fork();}process.exit();}functionchildProcess(){console.log(`Worker ${process.pid} started and finished`);process.exit();}
letworkers=[];functionmasterProcess(){console.log(`Master ${process.pid} is running`);// Fork workersfor(leti=0;i<numCPUs;i++){console.log(`Forking process number ${i}...`);constworker=cluster.fork();workers.push(worker);// Listen for messages from workerworker.on('message',function(message){console.log(`Master ${process.pid} recevies message '${JSON.stringify(message)}' from worker ${worker.process.pid}`);});}// Send message to the workersworkers.forEach(function(worker){console.log(`Master ${process.pid} sends message to worker ${worker.process.pid}...`);worker.send({msg: `Message from master ${process.pid}`});},this);}
$nodeapp.jsMaster4045isrunningForkingprocessnumber0...Forkingprocessnumber1...Master4045sendsmessagetoworker4046...Master4045sendsmessagetoworker4047...Worker4047startedWorker4047sendsmessagetomaster...
Worker4047finishedMaster4045receviesmessage'{"msg":"Message from worker 4047"}'fromworker4047Worker4047receviesmessage'{"msg":"Message from master 4045"}'Worker4046startedWorker4046sendsmessagetomaster...Worker4046finishedMaster4045receviesmessage'{"msg":"Message from worker 4046"}'fromworker4046Worker4046receviesmessage'{"msg":"Message from master 4045"}'
小结
cluster 模块为 NodeJS 提供了充分利用 CPU 所需的功能,不仅弥补了 child process 模块的不足,如提供了大量工具来处理进程:启动,停止和管道输入/输出等,而且帮助我们能轻松创建子进程,通过创建 IPC 通道来进行父子进程间的通信。尽管在这篇文章中没能体现所有功能,但它对应用带来性能上的提升是不争的事实。下篇文章我将介绍 HTTP 服务中 cluster 模块的作用。
The text was updated successfully, but these errors were encountered:
NodeJS 是单进程应用,这意味着默认情况下它不会利用多核系统。如果你有一个8核的 CPU,并且通过
$ node app.js
来运行一个 Node 程序,那么它只会在一个进程中运行,其余的 CPU 将会浪费掉。幸运的是NodeJS 提供了一个 cluster 模块,它提供了一系列的函数和属性,来帮助我们创建能充分使用 CPU 的程序。不足为奇,cluster 模块中能最大化使用 CPU 正是通过衍生(fork)子进程的方式来达到的,类似于老 fork() 系统调用 Unix 系统。
cluster 模块介绍
cluster 模块包含了一系列的函数和属性,来帮助我们衍生子进程并充分利用多核系统。
通过 cluster 模块,父进程衍生出来的子进程可通过 IPC 通道来与父进程进行通信。记住进程之间是不共享内存的,是相互独立的内存空间
下面是引用了 NodeJS 官方文档来解释 cluster 模块
所以大部分的工作其实是由 child_process 模块来完成的,它可以产生新的进程并且帮助他们进行通信,比如创建管道(pipes)。推荐阅读文章你所不知道的Node.js子进程。
简单用例
让我们来看一个简单的例子:
保存代码为
app.js
并执行$ node app.js
。打印结果类似如下:代码解释
当我们执行
app.js
的时候,操作系统会创建一个进程来运行我们的代码。我们引入cluster
模块,并通过isMaster
属性来判断是不是主进程。因为是第一个进程,所以isMaster
值为true
,接着执行masterProcess
函数。在masterProcess
函数中根据 CPU 个数,从当前进程中循环fork
出相同的子进程数。通过
fork
方法创建的进程,就像是命令行中执行$node app.js
一样,也就是说现在有多个进程在跑app.js
的代码。当每个子进程被创建和执行的时候,做的是跟第一次父进程一样的事,引入
cluster
模块执行if
判断,不同的是现在isMaster
为false
,所以他们执行childProcess
函数。父子进程通信
子进程一旦被创建,主进程和子进程之间的 IPC 通道也会被创建,我们可以通过
send()
方法来进行通信,send()
方法接受一个 object 对象作为参数。因为他们是不同的进程(不是线程),所以不能通过内存共享的方式来进行通信。在主进程中,我们可以使用进程引用(即
someChild.send({...})
)向子进程发送消息,并且在子进程内,我们可以简单地使用当前进程引用向主进程发送消息process.send()
。修改
childProcess
函数如下:我们通过
process.on('message', handler)
来监听message
事件,然后通过process.send({...})
来发送消息。这里的消息是一个 Object 对象。在
masterProcess
函数中,我们通过循环创建了 CPU 数等量的子进程,其中cluster.fork()
返回的是一个子进程对象,我们把它存储在workers
数组中,同时监听由子进程发来的信息。另外我们也通过worker.send({...})
从主进程往对应子进程发送消息。打印结果如下:
小结
cluster 模块为 NodeJS 提供了充分利用 CPU 所需的功能,不仅弥补了 child process 模块的不足,如提供了大量工具来处理进程:启动,停止和管道输入/输出等,而且帮助我们能轻松创建子进程,通过创建 IPC 通道来进行父子进程间的通信。尽管在这篇文章中没能体现所有功能,但它对应用带来性能上的提升是不争的事实。下篇文章我将介绍 HTTP 服务中 cluster 模块的作用。
The text was updated successfully, but these errors were encountered: