引用链接
前言
在我开发项目的时候,遇到一个问题,当我把一些简单的数据缓存在内存的时候,在本地开发是没问题的,但部署到测试环境后,发现缓存没生效。后面发现问题出现在部署时,用的是多进程模式,而本地只是单进程。这里总结下 EggJs 框架多进程使用遇到的问题和解决方法
主进程、代理进程和子进程
先根据文档,说明下这三个进程是什么来
- 主进程
- 整个服务最重要的进程,负责生成管理代理进程和子进程
- 代理进程
- 由主进程生成,因为主进程是不参与处理业务功能的,比如接收请求等,但我只想一个进程去做一些特定的事情,这时候就用代理进程,但代理进程也有它的局限性
- 当代理进程发生未捕获异常,不会被重启,需要人工处理。所以不应该将大量的业务处理交由代理进程
- 子进程
- 由主进程生成,负责处理请求等业务功能,子进程的多少,根据配置或者服务器的 cpu 核数决定
内容来自 EggJs 文档:
shell
+--------+ +-------+
| Master |<-------->| Agent |
+--------+ +-------+
^ ^ ^
/ | \
/ | \
/ | \
v v v
+----------+ +----------+ +----------+
| Worker 1 | | Worker 2 | | Worker 3 |
+----------+ +----------+ +----------+
# 启动时序
+---------+ +---------+ +---------+
| Master | | Agent | | Worker |
+---------+ +----+----+ +----+----+
| fork agent | |
+-------------------->| |
| agent ready | |
|<--------------------+ |
| | fork worker |
+----------------------------------------->|
| worker ready | |
|<-----------------------------------------+
| Egg ready | |
+-------------------->| |
| Egg ready | |
+----------------------------------------->|
进程间如何通信?
EggJs 文档图:
shell
广播消息: agent => all workers
+--------+ +-------+
| Master |<---------| Agent |
+--------+ +-------+
/ | \
/ | \
/ | \
/ | \
v v v
+----------+ +----------+ +----------+
| Worker 1 | | Worker 2 | | Worker 3 |
+----------+ +----------+ +----------+
指定接收方: one worker => another worker
+--------+ +-------+
| Master |----------| Agent |
+--------+ +-------+
^ |
send to / |
worker 2 / |
/ |
/ v
+----------+ +----------+ +----------+
| Worker 1 | | Worker 2 | | Worker 3 |
+----------+ +----------+ +----------+
子进程之间通信、子进程和代理进程通信,都是经过主进程进行传播的,文档有列出对应的 api
- app.messenger.broadcast
- app.messenger.sendToApp
- app.messenger.sendToAgent
- agent.messenger.sendRandom
- agent.messenger.sendTo
当 egg-ready
的时候,才可以进行消息通信
遇到的问题如何解决?
怎样才能知道所有的子进程都 ready
了?
app.js
javascript
app.messenger.once('egg-ready', () => {
app.messenger.sendToAgent('worker-ready', {});
});
agent.js
javascript
const workers = agent.options.workers;
let readyWorkers = 0;
agent.messenger.on('worker-ready', () => {
readyWorkers++;
if (readyWorkers === workers) {
agent.logger.info('============ all worker ready ===============');
agent.messenger.sendRandom('all-worker-ready', {});
}
});
当子进程 ready
的时候,向 agent
进程发送 ready
,而 agent
进程收到子进程都 ready
后(根据 workers 判断有多少子进程),然后随机告诉一个子进程进行一些业务操作
如何解决多进程间的资源不同问题?
了解了各个进程的作用和如何通信后,就可以解决该问题了。我这里的解决方案很简单,每个子进程都维护一份自己的缓存数据,当数据有变动的时候,通知 agent
进程进行修改,然后再广播所有的子进程进行数据更新,从而达到缓存数据一致
如何子进程没有发送 ready
给 agent
怎么办?
需要补充这流程的处理…todo