-
Notifications
You must be signed in to change notification settings - Fork 93
Open
Description
主进程和子进程
const cluster = require('cluster');
if (cluster.isMaster) {
console.log('这是主进程');
cluster.fork();
cluster.fork();
} else if (cluster.isWorker) {
console.log(`这是工作进程 #${cluster.worker.id}`);
}- 在主进程中 cluster 表示主进程(用于监听、发送事件), process 是本身的进程,worker 表示子进程,通过 cluster.workers 获取
- 在子进程中 process 表示子进程(用于监听、发送事件),也可以通过 cluster.worker 表示当前子进程
cluster.worker.process 等价于 process(在子进程中)
const cluster = require('cluster');
const http = require('http');
console.log(cluster.isMaster); // 这里如果我电脑是八核,则会打印一个true,七个false
// 一个主进程 判断是否主进程
if (cluster.isMaster) {
// 跟踪 http 请求。
let numReqs = 0;
setInterval(() => {
console.log(`请求的数量 = ${numReqs}`);
}, 1000);
// 对请求计数。
function messageHandler(msg) {
if (msg.cmd && msg.cmd === 'notifyRequest') {
numReqs += 1;
}
}
// 启动 worker 并监听包含 notifyRequest 的消息。
// 循环查找电脑核心,分配进程
const numCPUs = require('os').cpus().length;
for (let i = 0; i < numCPUs; i++) {
// 生成多个工作进程(子进程)
cluster.fork();
}
for (const id in cluster.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 (const id in cluster.workers) {
callback(cluster.workers[id]);
}通信
主进程全局监听来自子进程的信息
// 全局监听
cluster.on('message', (worker, msg) => {
console.log(msg)
})
// 遍历所有子进程监听
for (const id in cluster.workers) {
// 监听工作进程发过来的信息
cluster.workers[id].on('message', messageHandler);
}子进程主动触发事件,与主进程通信
process.send({
cmd: 'notifyRequest',
msg: 'hi'
}, () => {
console.log('send')
});主进程主动和子进程通信
const cluster = require('cluster');
if (cluster.isMaster) {
const worker = cluster.fork();
setInterval(() => {
worker.send('你好');
}, 1000)
} else if (cluster.isWorker) {
process.on('message', (msg) => {
console.log(msg)
process.send(msg);
});
}伪造多请求
可以使用多个子进程发送数据,伪造请求:
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log(`主进程 ${process.pid} 正在运行`);
// 衍生工作进程。
for (let i = 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} 已启动`);
}参考文档
Metadata
Metadata
Assignees
Labels
No labels
