目标
- 在主进程中完成以下事情:
- 每隔1秒钟输出,当前请求的数量
- 创建等同于CPU数量的进程
- 对每个进程施加一个处理函数,用于统计请求的数量
- 在各个CPU的进程中完成以下事情
- 监听8000端口的请求,并返回最简单的信息
- 发送事件,以触发主进程中施加的事件处理函数
前置知识
- process.pid
在主进程cluster.isMaster
中,process.id
是主进程的id
在工作进程(子进程)cluster.isWorker
中,process.id
是工作进程(子进程)的id
- 获取cpu的数量
const numCPUs = require('os').cpus().length;
- 判断一个进程是否为主进程
const cluster = require('cluster');
if(cluster.isMaster) { ... }
- 创建一个新进程
const cluster = require('cluster');
const work = cluster.fork();
实现
const cluster= require('cluster');
const http = require('http');
if(cluster.isMaster) {
// 主进程
let count = 0;
// 每隔1秒钟,就输出当前的访问次数
setInterval(()=>{
console.log(`访问次数为: ${count}`)
}, 1000);
let numCPUs = require('os').cpus().length;
for(let i =0 ; i < numCPUs ; i++) {
cluster.fork(); // 创建等同于cpu核数的进程
}
for(let id in cluster.workers){
cluster.workers[id].on('message', (msg) =>{
if(msg.cmd && msg.cmd === 'notifyRequest') {
count++;
}
})
}
} else {
// 子进程
http.Server((req, res) => {
if(req.url !== '/favicon.ico') {
res.writeHead(200);
res.end('Hi Marron');
// 通知执行 cmd.notifyRequest 事件
process.send({cmd: 'notifyRequest'});
}
}).listen(8000)
}
扩展
- 由于node.js是单线程.很容易卡死而导致崩溃.如下
const Koa = require('koa');
const app = new Koa();
app.use(async (ctx, next) =>{
aaa();
await next();
ctx.body = 'marron';
});
app.listen(3000);
- 说明会直接报错
ReferenceError: aaa is not defined
,会直接退出当前进程. - 思路: 可以在主进程中监听,一旦发现有进程死亡,就开启新的进程.
综上所述,明确在主进程中的目标:
- 开启等同于CPU核数的进程,并将进程保存在进程组(workers)对象中.
- 监听进程的死亡,一旦发现.就创建新的进程,并将新的进程替换挂掉的那个进程
子进程:
- 创建一个http服务器监听3000端口
- 当访问该端口时,以一定的几率报错(让当天进程死亡).
const cluster = require('cluster');
const os = require('os');
const numCPUs = os.cpus().length;
const process = require('process');
// 保存进程组的对象
const workers = {};
if(cluster.isMaster) {
// 主进程
for(let i = 0; i< numCPUs; i++){
const worker = cluster.fork(); // 创建一个进程
workers[worker['pid']] = worker; // 保存当前进程
}
cluster.on('death', function(worker){
// 监听进程的死亡
nWorker = cluster.fork(); // 新建进程
workers[worker.pid] = nWorker;
})
} else {
const Koa = require('koa');
const app = new Koa();
app.use(async (ctx, next) => {
Math.random > 0.95 ? aaa() : ''; // 手动挂掉进程
console.log(`current process ${process.pid}`);
await next();
ctx.body = 'marron';
})
app.listen(3000);
}
当挂的时候,自动重新启动当前服务