2026年15天学习完eggjs 第13天
多进程模型和进程间通讯
1. 背景与问题
-
Node.js 单线程特性导致单个进程只能利用 1 个 CPU 核心,无法发挥多核服务器的性能优势。
-
官方通过
Cluster模块实现多进程,Egg.js 在此基础上扩展为更健壮的企业级多进程模型。
2. 核心进程角色
|
进程类型 |
数量 |
核心作用 |
稳定性 |
业务代码 |
|
Master |
1 |
进程管理、消息转发、异常重启 |
极高 |
不运行 |
|
Agent |
1 |
后台公共任务(如日志归档、长连接) |
高 |
少量 |
|
Worker |
通常为 CPU 核数 |
处理用户请求、执行业务代码 |
一般 |
运行 |
3. 关键机制
-
进程守护:Worker 异常退出时,Master 会立即重启新 Worker;Agent 异常时仅记录日志等待人工处理,避免频繁重启影响公共服务。
-
启动时序:Master → Agent → Worker,所有进程就绪后触发
egg-ready事件,此时才能安全使用 IPC 通讯。 -
IPC 通讯:通过
messenger对象封装,仅支持 Master ↔ Worker/Agent 直接通讯,Worker 间需 Master 转发。
常用 API:
// 发送消息
app.messenger.sendToAgent('event', data);
app.messenger.sendToApp('event', data);
app.messenger.broadcast('event', data);
// 接收消息
app.messenger.on('event', (data) => { /* 处理逻辑 */ });
4. Agent 机制
框架的启动时序如下:
- Master 启动后先 fork Agent 进程。
- Agent 初始化成功后,通过 IPC 通道通知 Master。
- Master 接着 fork 多个 App Worker。
- App Worker 初始化成功后,通知 Master。
- 所有进程初始化成功后,Master 通知 Agent 和 Worker,应用启动成功。
// agent.js
module.exports = agent => {
// 在这里写你的初始化逻辑。
// 你还可以通过 messenger 对象发送消息给 App Worker。
// 但是,需要等 App Worker 启动成功后才能发送,否则可能丢失消息。
agent.messenger.on('egg-ready', () => {
const data = { ... };
agent.messenger.sendToApp('xxx_action', data);
});
};
// app.js
module.exports = (app) => {
app.messenger.on('xxx_action', (data) => {
// ...
});
};
5. 实战场景:缓存更新
结合定时任务 + IPC 实现三种缓存更新策略:
-
兜底更新:所有 Worker 每 10 分钟拉取最新数据。
-
主动检查:单个 Worker 每 10 秒检查数据源变化,通过 IPC 通知所有 Worker 更新。
-
被动推送:Agent 监听消息中间件,收到变更后广播给所有 Worker。
实战demo:test-egg/eggdemo07 at main · EggFlower10/test-egg
二、国际化(I18n)
1. 基础配置
-
默认语言:
en-US,可通过配置修改为简体中文:// config/config.default.js exports.i18n = { defaultLocale: 'zh-CN', }; -
语言切换优先级:
query>cookie>header,支持自定义参数名和 Cookie 过期时间
2. 多语言文件
-
存放路径:
config/locale/*.js或*.json,框架会自动合并应用、框架、插件的多语言配置。 -
示例(
zh-CN.js):module.exports = { 'Email': '邮箱', 'Welcome back, %s!': '欢迎回来,%s!', };
3. 多语言文本使用
-
在 Controller 中通过
ctx.__()(或别名ctx.gettext())获取:ctx.__('Welcome back, %s!', ctx.user.name); -
在 View(如 Nunjucks)中直接使用:
<li>{{ __('Email') }}:{{ user.email }}</li> -
支持
%s占位符和数组下标占位符(如{0}、{1})。
三、View 模板渲染
1. 核心设计
-
框架内置
@eggjs/view作为基础层,支持多模板引擎以插件形式引入(如@eggjs/view-nunjucks),保持渲染 API 统一。
2. 快速上手(以 Nunjucks 为例)
-
安装插件:
npm i @eggjs/view-nunjucks -
启用插件:
// config/plugin.js exports.nunjucks = { enable: true, package: 'egg-view-nunjucks', }; -
配置插件:
// config/config.default.js exports.view = { root: 'app/view', // 模板根目录 defaultViewEngine: 'nunjucks', // 全局默认模板引擎 defaultExtension: '.nj', // 默认文件后缀 mapping: { '.nj': 'nunjucks' }, // 后缀与引擎映射 };
3. 渲染接口
框架在 Context 上提供三个渲染接口:
-
ctx.render(name, locals):渲染模板并赋值给ctx.body。 -
ctx.renderView(name, locals):仅渲染模板,不赋值。 -
ctx.renderString(tpl, locals, options):渲染模板字符串。
示例:
await ctx.render('home.nj', { name: 'Egg.js' });
ctx.body = await ctx.renderString('Hi, {{ name }}', { name: 'Egg.js' });
4. 本地变量(Locals)
-
app.locals:全局变量,在app.js中配置,所有请求共享。 -
ctx.locals:请求级变量,会自动合并app.locals,且仅首次访问时合并。 -
框架会自动将
render传入的data合并到ctx.locals,并注入ctx、request、helper等对象。
5. 辅助与安全
-
Helper:在
app/extend/helper.js中扩展方法,模板中直接调用(如helper.lowercaseFirst(str))。 -
安全插件:内置
@eggjs/security,提供helper.shtml、surl等安全转义函数,避免 XSS 风险。
更多推荐



所有评论(0)