- 路由分包管理
- 线上监控 alinode or easy monitory
- 接入 apollo 配置中心
- 轻量级事件触发器 egg-bus
- 通用的异常处理器
- 通用的请求日志
路由分包管理
在 egg 中一个路由和控制器的绑定管理如下进行配置
// app/router.js
module.exports = app => {
const { router, controller } = app;
router.get('/user/:id', controller.user.info);
};
复制代码
上述方式会存在一个问题,在业务推进过程中,业务越来越复杂,这样路由统一管理就会显得很杂乱,最好的方式还是采用分包管理
在自己的业务域下进行管理.
${rootPath}/router.js
const v1Router = router.namespace('/api/v1');
const v1Controller = controller.v1;
const v1RouterBasePath = path.resolve(__dirname, './routes/v1');
const requireRouters = async (basePath, router, controller, middleware) => {
const files = await fsPromises.readdir(basePath);
files.forEach(file => {
require(path.join(basePath, file))(router, controller, middleware);
});
};
requireRouters(v1RouterBasePath, v1Router, v1Controller, middleware);
复制代码
分别通过读取 controller 下的文件和 router 下的文件,进行绑定。
线上监控 alinode
alinode 有一些小问题,windows 上不可调试,还有就是整个环境的安装比较麻烦。我们这边在线上使用的监控还是 easy-monitor
线上监控 easy-monitor
easy-monitor 部署起来还是比较简单的,windows 可以调试。
集成 apollo 配置中心
install
npm i egg-apollojs-no-schedule --save
复制代码
plugins.js
exports.apollojs = {
enable: true,
package: 'egg-apollojs-no-schedule',
};
复制代码
app/apollo/config.js
module.exports = {
configServerUrl: <configServerUrl>, // 配置中心地址
appId: [appId], // appId
clusterName: "default",
namespaceName: 'application' // 注意这里的namespace 不能写错了,需要与 apollo 上的配置一一对应
};
复制代码
preload.js
require('egg-apollojs-no-schedule')
.init(__dirname + '/config/apollo.js');
复制代码
config.default.js
// 加载process.env
require('egg-apollojs-no-schedule').apollo.setEnv();
复制代码
package.json
"scripts": {
"start": "node preload.js && egg-scripts start --daemon --title=<application name> --port=<port>"
}
复制代码
使用
以 配置线上 mongodb 数据库连接地址为例
apollo 中 配置的值
mongoose.url = "mongodb://127.0.0.1/test"
复制代码
在 config.default.js 中使用配置为
config.mongoose = {
url: process.env['mongoose.url'],
options: {
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true,
useFindAndModify: false,
bufferMaxEntries: 0,
poolSize: 1000,
},
};
复制代码
轻量级事件触发器 egg-bug
安装
npm i egg-bus --save
复制代码
使用
exports.bus = {
enable: true,
package: 'egg-bus',
};
复制代码
配置
config.default.js
// {app_root}/config/config.default.js
exports.bus = {
debug: true, // Debug 模式下会打印更多日志信息
concurrency: 1, // Bull 中队列处理的并发数:https://github.com/OptimalBits/bull/blob/develop/REFERENCE.md#queueprocess
listener: {
ignore: null, // 忽略目录中的某些文件,https://eggjs.org/zh-cn/advanced/loader.html#ignore-string
baseDir: 'listener',
options: { // Bull Job 配置: https://github.com/OptimalBits/bull/blob/develop/REFERENCE.md#queueadd
attempts: 5,
backoff: {
delay: 3000,
type: 'fixed',
},
}
},
job: {
// 与 listener 一致,唯一不同的就是 默认 baseDir 的值为 `job`
},
bull: { // Bull 队列配置:https://github.com/OptimalBits/bull/blob/develop/REFERENCE.md#queue
redis: {
host: 'localhost',
port: 6379,
db: 0,
},
},
queue: {
default: 'default', // 默认队列名称
prefix: 'bus', // 队列前缀
},
queues: { // 针对不同队列单独配置
// 比如针对默认队列更改 redis 端口
default: {
redis: {
port: 6380,
},
}
},
};
复制代码
通用的异常处理器
/app/middleware/error_handler.js
'use strict';
module.exports = (option, app) => {
return async function (ctx, next) {
try {
await next();
} catch (err) {
// 生产环境时 500 错误的详细错误内容不返回给客户端,因为可能包含敏感信息
let { code = 'Error', message = 'Error', status = 500 } = err;
app.emit(status === 500 ? 'error' : 'warn', err, this);
message = status === 500 && app.config.env === 'prod' ? 'Internal Server Error' : err.message;
if (typeof code === 'number') {
code = 'InternalError';
message = 'The request processing has failed due to some unknown error, exception or failure.';
}
ctx.body = {
code,
message,
};
if (status === 422) {
ctx.body.detail = err.errors;
}
ctx.status = status;
}
};
};
复制代码
统一的处理错误,如果是在测试环境就将错误详细信息抛出,如果在生产环境就抛出统一的错误。
通用的请求日志
module.exports = () => async (ctx, next) => {
ctx.logger.info(`
headers:${JSON.stringify({
referer: ctx.headers.referer,
token: ctx.headers.token,
accessToken: ctx.headers.accesstoken,
openId: ctx.headers.openid,
devieId: ctx.headers.deviceid,
})}
body:${JSON.stringify(ctx.request.body)}
`);
await next();
ctx.logger.info(`response: ${JSON.stringify(ctx.response.body)}`);
};
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END