egg中的多进程模型
2018年11月19日
多进程间的模型
Master:
在这个模型下,Master 进程承担了进程管理的工作(类似 pm2),不运行任何业务代码,我们只需要运行起一个 Master 进程它就会帮我们搞定所有的 Worker、Agent 进程的初始化以及重启等工作了。
Master 进程的稳定性是极高的,线上运行时我们只需要通过 egg-scripts 后台运行通过 egg.startCluster
启动的 Master 进程就可以了,不再需要使用 pm2 等进程守护模块。
Agent:
在大部分情况下,我们在写业务代码的时候完全不用考虑 Agent 进程的存在,但是当我们遇到一些场景,只想让代码运行在一个进程上的时候,Agent 进程就到了发挥作用的时候了。
由于 Agent 只有一个,而且会负责许多维持连接的脏活累活,因此它不能轻易挂掉和重启,所以 Agent 进程在监听到未捕获异常时不会退出,但是会打印出错误日志,我们需要对日志中的未捕获异常提高警惕。
Worker:
Worker 进程负责处理真正的用户请求和定时任务的处理。而 Egg 的定时任务也提供了只让一个 Worker 进程运行的能力,所以能够通过定时任务解决的问题就不要放到 Agent 上执行。
Worker 运行的是业务代码,相对会比 Agent 和 Master 进程上运行的代码复杂度更高,稳定性也低一点,当 Worker 进程异常退出时,Master 进程会重启一个 Worker 进程。
'use strict';
const cluster = require('cluster');
if (cluster.isMaster) {
const worker = cluster.fork();
worker.send('hi there');
worker.on('message', msg => {
console.log(`msg: ${msg} from worker#${worker.id}`);
});
} else if (cluster.isWorker) {
process.on('message', (msg) => {
process.send(msg);
});
}
app.messenger.broadcast(action, data)
:发送给所有的 agent / app 进程(包括自己)app.messenger.sendToApp(action, data)
: 发送给所有的 app 进程- 在 app 上调用该方法会发送给自己和其他的 app 进程
- 在 agent 上调用该方法会发送给所有的 app 进程
app.messenger.sendToAgent(action, data)
: 发送给 agent 进程- 在 app 上调用该方法会发送给 agent 进程
- 在 agent 上调用该方法会发送给 agent 自己
agent.messenger.sendRandom(action, data)
:- app 上没有该方法(现在 Egg 的实现是等同于 sentToAgent)
- agent 会随机发送消息给一个 app 进程(由 master 来控制发送给谁)
app.messenger.sendTo(pid, action, data)
: 发送给指定进程
// app.js
module.exports = app => {
// 注意,只有在 egg-ready 事件拿到之后才能发送消息
app.messenger.once('egg-ready', () => {
app.messenger.sendToAgent('agent-event', { foo: 'bar' });
app.messenger.sendToApp('app-event', { foo: 'bar' });
});
}
egg-ready:
上面的示例中提到,需要等 egg-ready
消息之后才能发送消息。只有在 Master 确认所有的 Agent 进程和 Worker 进程都已经成功启动(并 ready)之后,才会通过 messenger 发送 egg-ready
消息给所有的 Agent 和 Worker,告知一切准备就绪,IPC 通道可以开始使用了。
接受:
在message上监听对应的action事件,就可以接受其他进程发送来的信息了。
app.messenger.on(action, data => {
// process data
});
app.messenger.once(action, data => {
// process data
});