NodeJS的JavaScript运行在单个进程的单个线程上,一个JavaScript执行进程只能利用一个CPU核心,而如今大多数CPU均为多核CPU,为了充分利用CPU资源,Node提供了child_process和cluster模块来实现多进程以及进程管理。本文将根据Master-Worker模式,搭建一个简单的服务器集群来充分利用多核CPU资源,探索进程间通信、负载均衡、进程重启等知识。
下图是Master-Worker模式,进程分为master进程和worker进程,master进程负责调度或管理worker进程,worker进程则负责具体的业务处理。在服务器层面,worker可以是一个服务进程,负责处理来自客户端的请求,多个worker便相当于多个服务器,从而构成一个服务器集群。master则是负责创建worker,将来自客户端的请求分配到各个服务器上去处理,并监控worker的运行状态以及进行管理等操作。
child_process模块提供了spawn()、exec()、execFile()、fork()这4个方法用于创建子进程,本文将使用fork()方法来创建子进程,fork()方法只需指定要执行的JavaScript文件模块,即可创建Node的子进程。下面是简单的HelloWorld示例,master进程根据CPU数量创建出相应数量的worker进程,worker进程中利用进程ID来标记自己。
父进程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/** * Created by PhpStorm. * User: iyahe@qq.com (天明) * Date: 2019/10/12 0012 * Time: 下午 15:32 * Description: */ const childProcess = require('child_process'); const cpuNum = require('os').cpus().length; console.log('CPU个数',cpuNum); for (let i = 0; i < cpuNum*10; ++i) { let worker = childProcess.fork('./write.js'); // 给子进程发消息 worker.send(JSON.stringify({id: i})); worker.on('message', (msg) => { console.log('我是父进程 我收到了 : ' + msg) }) } |
子进程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
/** * Created by PhpStorm. * User: iyahe@qq.com (天明) * Date: 2019/10/12 0012 * Time: 下午 15:46 * Description: */ const os = require('os'); var fs = require("fs"); const thatPid = process.pid; const files = process.cwd() +'/logs/' + thatPid + '.log'; const times = (new Date()).getTime() + '\n'; const startTime = (new Date()).getTime(); const maxLen = 1000; process.on('message', (msg) => { console.log('子进程收到消息: ' + msg) }); for (var i = 0; i < maxLen; i++) { fs.appendFileSync(files, times); } let allTime = (new Date()).getTime()-startTime; // 给父进程发消息 process.send(thatPid + 'jin: Hi master. 我处理完了: 写入' + maxLen + '次, 一共耗时: ' + allTime + 'ms') |
log输出内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
我是父进程 我收到了 : 8800jin: Hi master. 我处理完了: 写入1000次, 一共耗时: 869ms 我是父进程 我收到了 : 11984jin: Hi master. 我处理完了: 写入1000次, 一共耗时: 1082ms 我是父进程 我收到了 : 11504jin: Hi master. 我处理完了: 写入1000次, 一共耗时: 1264ms 我是父进程 我收到了 : 14756jin: Hi master. 我处理完了: 写入1000次, 一共耗时: 1473ms 我是父进程 我收到了 : 12772jin: Hi master. 我处理完了: 写入1000次, 一共耗时: 1669ms 我是父进程 我收到了 : 4064jin: Hi master. 我处理完了: 写入1000次, 一共耗时: 1100ms 我是父进程 我收到了 : 7860jin: Hi master. 我处理完了: 写入1000次, 一共耗时: 1337ms 我是父进程 我收到了 : 12388jin: Hi master. 我处理完了: 写入1000次, 一共耗时: 1030ms 我是父进程 我收到了 : 12216jin: Hi master. 我处理完了: 写入1000次, 一共耗时: 1017ms 我是父进程 我收到了 : 12784jin: Hi master. 我处理完了: 写入1000次, 一共耗时: 1089ms 我是父进程 我收到了 : 6652jin: Hi master. 我处理完了: 写入1000次, 一共耗时: 989ms 我是父进程 我收到了 : 12980jin: Hi master. 我处理完了: 写入1000次, 一共耗时: 779ms 我是父进程 我收到了 : 9960jin: Hi master. 我处理完了: 写入1000次, 一共耗时: 978ms ..... |
还是挺好用的,看这执行情况, 应该比php效率更高~~~