《2026年15天学会eggjs第13天》
,},// 可访问ctx三类进程分工明确,Master管理、Agent处理公共任务、Worker处理请求。IPC通信依赖messenger,必须在egg-ready事件后发送消息。Worker异常自动重启,Agent异常需人工处理。
贪多嚼不烂,每天学点蛋,今天我们来学:
多进程模型、i18n 国际化、View 模板渲染
一、多进程模型
1.1 核心目的
Node.js 单线程无法利用多核 CPU,多进程模型可解决:资源浪费、单点故障、无进程级负载均衡的问题,充分发挥服务器性能。
1.2 进程类型与分工
|
进程类型 |
数量 |
核心作用 |
稳定性 |
运行业务代码 |
|---|---|---|---|---|
|
Master |
1个 |
进程管理、消息转发 |
非常高 |
否 |
|
Agent |
1个 |
后台任务(长连接、定时任务) |
高 |
少量 |
|
Worker |
CPU核数 |
处理用户请求 |
一般 |
是 |
Master就是包工头、Agent是秘书、Worker是工人
1.3 启动顺序与时序
核心顺序:Master → Agent → 多个 Worker
关键时序:所有进程启动完成后,触发 egg-ready 事件(在此之前发消息可能丢失)。
1.4 进程守护与异常处理
-
Worker 异常:自动优雅退出,Master 立即重启新 Worker,保证进程总数不变。
-
Agent 异常:不自动重启,仅记录日志,需人工介入(保障稳定性)。
1.5 进程间通信(IPC)
核心 API(发送消息)
// 1. 广播到所有进程
app.messenger.broadcast(action, data);
// 2. 发送到所有 Worker
app.messenger.sendToApp(action, data);
// 3. 发送到 Agent
app.messenger.sendToAgent(action, data);
// 4. 随机发送到某个 Worker(仅 Agent 可用)
agent.messenger.sendRandom(action, data);
// 5. 发送到指定 PID 进程
app.messenger.sendTo(pid, action, data);
接收消息
// 多次监听
app.messenger.on('config-update', (data) => { console.log('收到配置:', data); });
// 仅监听一次
app.messenger.once('config-update', (data) => { console.log('首次收到配置:', data); });
1.6 Agent 适用场景
✅ 适合:长连接客户端、定时任务、全局唯一后台任务 | ❌ 不适合:处理HTTP请求、复杂业务逻辑、需频繁重启任务
1.7 实战示例:配置热更新
// agent.js(发送配置)
agent.messenger.once('egg-ready', () => {
// 初始配置
agent.messenger.sendToApp('config-update', { version: '1.0.0', feature: { newUI: true } });
// 每15秒更新配置
setInterval(() => {
agent.messenger.sendToApp('config-update', { version: '1.0.' + Date.now() });
}, 15000);
});
// app.js(接收配置)
app.currentConfig = null;
app.messenger.on('config-update', (config) => {
app.currentConfig = config;
app.logger.info(`[Worker ${process.pid}] 收到配置:`, config);
});
// controller 使用
async getConfig() {
const { ctx } = this;
ctx.body = { workerPid: process.pid, config: ctx.app.currentConfig };
}
二、国际化(i18n)
2.1 安装与配置
npm install @eggjs/i18n --save
// config/plugin.js
exports.i18n = { enable: true, package: '@eggjs/i18n' };
// config/config.default.js
config.i18n = {
defaultLocale: 'zh-CN', // 默认语言
queryField: 'locale', // URL参数切换:?locale=en-US
cookieField: 'locale', // Cookie字段名
cookieMaxAge: '1y', // Cookie有效期1年
};
2.2 语言切换机制
优先级(从高到低):URL Query参数 → Cookie → HTTP Header(Accept-Language)
切换后自动设置Cookie,下次访问无需重复切换。
2.3 语言文件
目录:config/locale/(必须是单数locale),支持JS/JSON两种格式
// config/locale/zh-CN.js
module.exports = {
'Email': '邮箱',
'Welcome back, %s!': '欢迎回来,%s!',
'Hello {0}! My name is {1}.': '你好 {0}!我的名字叫 {1}。'
};
2.4 使用方法
// Controller 中(__ 与 gettext 等价)
ctx.__('Email'); // 邮箱
ctx.__('Welcome back, %s!', 'Shawn'); // 欢迎回来,Shawn!
ctx.__('Hello {0}! My name is {1}.', ['foo', 'bar']); // 你好 foo!我的名字叫 bar。
// 获取当前语言
const currentLocale = ctx.getLocale(); // 'zh-CN' / 'en-US'
模板中使用:{{ __('Email') }}、{{ __('Welcome back, %s!', user.name) }}
2.5 注意事项
-
目录名必须是
locale,不可写为 locals。 -
key 推荐用英文原文,方便维护(如 'Welcome back' 而非 'welcome_back')。
-
应用、框架、插件的语言文件会合并,相同key优先级:应用 > 框架 > 插件。
三、View 模板渲染
3.1 安装与配置
npm install egg-view egg-view-nunjucks --save
// config/plugin.js
exports.nunjucks = { enable: true, package: 'egg-view-nunjucks' };
// config/config.default.js
config.view = {
defaultViewEngine: 'nunjucks', // 默认模板引擎
defaultExtension: '.nj', // 默认扩展名
mapping: { '.nj': 'nunjucks' } // 后缀与引擎映射
};
3.2 三种渲染方法
|
方法 |
作用 |
自动赋值ctx.body |
适用场景 |
|---|---|---|---|
|
ctx.render(name, data) |
渲染模板文件 |
✅ 是 |
最常用,直接返回渲染结果 |
|
ctx.renderView(name, data) |
仅渲染模板 |
❌ 否 |
需二次处理渲染结果 |
|
ctx.renderString(tpl, data) |
渲染模板字符串 |
❌ 否 |
动态模板、邮件模板 |
3.3 模板变量(Locals)
-
app.locals:全局变量,所有模板可访问(如应用名、版本号)。
-
ctx.locals:请求级变量,自动合并app.locals,框架自动注入ctx、request、helper。
-
合并机制:修改app.locals不影响当前请求的ctx.locals(已缓存),赋值ctx.locals会自动合并不覆盖。
3.4 Helper 辅助函数
定义(app/extend/helper.js)
module.exports = {
lowercaseFirst(str) { return str ? str[0].toLowerCase() + str.slice(1) : ''; },
formatDate(date) { return new Date(date).toLocaleDateString('zh-CN'); },
// 可访问ctx
getCurrentUser() { return this.ctx.session.user; }
};
3.5 常用模板语法(Nunjucks)
// 变量输出
{{ name }} {{ user.email }} {{ list[0] }}
// 条件判断
{% if user.isVip %}VIP{% elif user.isMember %}会员{% else %}普通{% endif %}
// 循环
{% for item in list %}{{ loop.index }}: {{ item.name }}{% endfor %}
// 过滤器
{{ name | upper }} {{ price | default('免费') }}
3.6 注意事项
-
Egg中ctx.state ≡ ctx.locals,推荐使用ctx.locals。
-
模板默认根目录:app/view/,渲染路径可省略默认扩展名.nj。
-
renderString无默认引擎时,需手动指定viewEngine: 'nunjucks'。
四、测试接口汇总
|
接口 |
功能 |
说明 |
|---|---|---|
|
http://localhost:7001/ |
首页 |
显示当前环境 |
|
http://localhost:7001/ipc-config |
IPC通信示例 |
查看Agent发送的配置(每15秒更新) |
|
http://localhost:7001/i18n |
i18n示例 |
默认显示中文 |
|
http://localhost:7001/i18n?locale=en-US |
切换语言 |
URL参数切换为英文 |
|
http://localhost:7001/view |
View渲染示例 |
综合展示模板功能 |
|
http://localhost:7001/view/render-view |
renderView方法 |
演示手动赋值ctx.body |
|
http://localhost:7001/view/render-string |
renderString方法 |
演示渲染字符串模板 |
五、核心要点总结
5.1 多进程模型
-
三类进程分工明确,Master管理、Agent处理公共任务、Worker处理请求。
-
IPC通信依赖messenger,必须在egg-ready事件后发送消息。
-
Worker异常自动重启,Agent异常需人工处理。
5.2 i18n 国际化
-
核心API:ctx.__() 或 ctx.gettext(),支持两种占位符(%s/%d/%j 和 {0}/{1})。
-
语言切换优先级:URL参数 > Cookie > HTTP Header。
-
语言文件存于config/locale/,key推荐用英文原文。
5.3 View 模板渲染
-
优先使用ctx.render(),其余两种方法需手动赋值ctx.body。
-
app.locals全局变量,ctx.locals请求级变量,自动合并并注入常用对象。
-
Helper通过app/extend/helper.js扩展,可访问ctx,用于模板格式化。
六、最佳实践
-
Agent:仅放长连接、定时任务等全局唯一任务,保证代码稳定。
-
i18n:key用英文,保持各语言文件key一致,合理设置默认语言。
-
View:复杂逻辑放Controller/Service,Helper职责单一,合理使用locals变量。
更多推荐



所有评论(0)