Skip to content

引用链接

  1. 多进程模型和进程
  2. 多进程研发模式增强

前言

在我开发项目的时候,遇到一个问题,当我把一些简单的数据缓存在内存的时候,在本地开发是没问题的,但部署到测试环境后,发现缓存没生效。后面发现问题出现在部署时,用的是多进程模式,而本地只是单进程。这里总结下 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 进程进行修改,然后再广播所有的子进程进行数据更新,从而达到缓存数据一致

如何子进程没有发送 readyagent 怎么办?

需要补充这流程的处理…todo