• 首页
  • nodejs
  • node.js 下 cluster 模块充分利用cpu资源实现群集功能

node.js 下 cluster 模块充分利用cpu资源实现群集功能


为什么会出现cluster ?


大概在 node.js V0.8 之前的版本,node.js 本身不提供多核多进程处理的解决方案,当然你可以使用第三方的开源包来实现.

直到V0.8之后的版本,node.js 内置了 cluster 功能,node.js 终于可以不依赖第三方cluster包来利用服务器多核,多线程资源.


node.js 内置模块 cluster 的出现,帮助我们轻松利用多核,多进程开发的难度及负载均衡群集.



cluster 是如何工作的 ?

工作进程是通过使用 child_process.fork 方法派送的,他们可以通过IPC (进程间通讯实现父进程和子进程相互传递句柄及通讯)


看下面的一个示例:

var cluster = require('cluster');
var http=require('http');
var cpu_num = require('os').cpus().length;

if (cluster.isMaster) {
    console.log("==启动主进程==");

    for (var i = 0; i < cpu_num; i++) {
        cluster.fork();
        //根据cpu的数量主进程 fork 了相同数量的子进程出来
    }

    cluster.on('listening',function(worker,address){
        console.log('listening: worker ' + worker.process.pid);
    });

    cluster.on('exit', function(worker, code, signal) {
        console.log('exit worker ' + worker.process.pid + ' died');
    });
} else {
    http.createServer(function(req, res) {
        res.writeHead(200);
        res.end("<a href='http://yijiebuyi.com'>一介布衣</a>\n");
    }).listen(7000);
}
29 Jul 17:44:02 - [nodemon] starting `node cluster.js`
==启动主进程==
listening: worker 39114
listening: worker 39116
listening: worker 39113
listening: worker 39115

看到上面的运行结果,主进程启动了4个子进程

其实我电脑是双核的,见下图

因为双通道,它认为是4核


cluster 默认有2个参数可以区分主进程和子进程.


cluster.isMaster  判断主进程: 返回 true or false

cluster.isWorker 判断子进程: 返回 true or false


if (cluster.isMaster) {
    这个逻辑判断分支里,主进程会根据cpu个数来 fork 相同数目的子进程
}else{
    这里的逻辑分支是,如果是子进程,就监听 7000 端口.
}

这样看来,我们4个子进程同时监听相同端口 7000 ,那么主进程干什么去了?

其实这时的主进程起到了协调,调度的作用,他把客户端过来的请求分发给子进程.


cluster 是如何调度协调子进程的?

cluster 内部有2中方法来调度

(1)循环调度

(2)系统调度


除windows 系统外,默认都是采用第一种 循环调度 的方法.

就是一共4个子进程,当主进程接到请求后,挨个从 子进程1到4派发任务,这样一直循环下去.


第二种系统调度,可能更加智能一点点,就是主进程拿到请求后优先派发给空闲的进程去处理.


每个子进程都是独立的进程,它们会根据您的程序的需要被终止或重新派生,

不会影响到其它工作进程。只要还有工作进程存在,服务器就会继续接受连接。

但是,Node 不会自动为您管理工作进程的数量.


cluster 主要的api有哪些?

  1. fork

    用来派生一个子进程

cluster.fork();

当主进程创建派生子进程时,会触发此事件.


2. online

    当fork 一个新的进程后,子进程会通知主进程,当主进程收到子进程的消息后,这时会触发 online 事件

    

online 和 fork 有什么区别?

针对主进程来说, fork 是一个主动的工程,当我派生新子进程后,及触发此事件.

online 对于主进程来说,是比较被动的,当子进程被创建后和主进程通讯成功,这时主进程才会触发 online 事件.


3.listening

    工作子进程监听的地址和端口.

cluster.on('listening', function(worker, address) {
  console.log("工作进程连接到 " + address.address + ":" + address.port);
});

4. exit

    工作子进程退出时,cluster 模块会分发此事件.

cluster.on('exit', function(worker, code, signal) {
  var exitCode = worker.process.exitCode;
  console.log('工作进程 ' + worker.process.pid + ' 被结束('+exitCode+')。正在重启...');
  cluster.fork();
});

上面的示例代码不仅仅是监听cluster 的 exit 事件,更重要的功能是重启子进程

如何重启, cluster.fork() 即可把此子进程重启.


这种模式非常像 forever 的工作模式,一个守护进程来监视所有的子进程,当任何一个'死'掉,马上让他原地满血满状态复活.





回到顶部