现在遇到一个需求,需要将数据库的配置文件放在 apollo 中进行管理,所以写了一个本地插件 egg-apollo 项目中进行异步获取配置,预计的想法是:
- 先执行 egg-apollo 插件,异步获取数据库配置
- 更新 this.config.sequelize 对象
- 初始 egg-sequelize 插件
但是现在无论把 egg-apollo 获取配置的方法写到loader哪个生命周期去,都无法阻止 egg-sequelize 比 egg-apollo 早执行,有啥有效的方法吗?
按照官方文档的执行顺序来说,我这样配置应该没得问题吧,先更新this.config,再初始化 egg-sequelize
试试 egg-apollo 在 agent 里面获取配置,写到文件。然后 app 里面读取文件塞到 config
这是我 egg-apollo 中 agent.js 中的代码
assert(agent.config.apolloDdz, 'apolloDdz config is required');
const config = await apollo.remoteConfigServiceSikpCache(agent.config.apolloDdz);
// this.coreLogger.info(`apollo 初始化完成${new Date()}`, bundle);
const configFilePath = __dirname + '/config/config.default.js';
if (fs.existsSync(configFilePath)) {
fs.unlinkSync(configFilePath);
}
let configText = "'use strict';\n";
configText = configText + 'module.exports = () => {\n return';
configText = configText + JSON.stringify(config);
configText = configText + '};';
fs.appendFileSync(configFilePath, configText);
现在遇到的问题是,项目使用 egg-bin debug 启动,如果把配置信息写到 config.default.js 中,会检查到代码有变化然后进行重启,然后继续获取配置文件,写到 config.default.js 中进入死循环
你应该写到 xx.json,然后 config 里面 require 这个文件。
然后 xx.json 这个配置到 egg-development 的 ignore 里面
感谢,已经实现
@atian25 现在我将获取配置的代码写在 agent.js 中,代码内容如下。但是在测试中,config中的 require json文件的代码运行的时间比 agent.js 中生成json文件早,导致无法加载报错,请问是我哪里操作错误了吗?
//agent.js
'use strict';
const assert = require('assert');
const fs = require('fs');
const apollo = require('./lib/apollo');
module.exports = async agent => {
agent.beforeStart(async () => {
assert(agent.config.apolloDdz, 'apolloDdz config is required');
const config = await apollo.remoteConfigServiceSikpCache(agent.config.apolloDdz);
const configFilePath = __dirname + '/config/apollo-config.json';
if (fs.existsSync(configFilePath)) {
fs.unlinkSync(configFilePath);
}
const configStr = JSON.stringify(config);
fs.appendFileSync(configFilePath, configStr);
agent.coreLogger.info(`apollo 初始化完成${new Date()}`);
});
};
//config.default.js
'use strict';
module.exports = () => {
const config = require('./apollo-config.json');
return config;
};
- mm.app 是把 agent 和 app 模拟在一个进程里面来加速测试的,可能这里的时序有问题。
- 可以实现新的生命周期的写法,beforeStart 已经是不推荐的了
- 如果还不行,就用 mm.cluster 的测试方式
@atian25 我上面的配置加载方式,现在项目启动就会直接报错,Error: Cannot find module ‘./apollo-config.json’。在 agent.js 先获取配置在写到json文件中去,然后在插件的 config.default.js 中进行加载,这个顺序是不是有问题呢?因为代码启动是不按照这个顺序执行的
现在解决办法是将读取 json 配置的方法,写到 config.prod.js 或者 config.local.js 中,不允许写在 config.default.js中
@ddzyan 可以带最小可复现仓库提交 issue 我们看看
@atian25 这是代码仓库,稍后我会添加到issue中 https://github.com/ddzyan/apollo-loader-test
按照egg-loader的文档说明,config的加载是在agent.js之前,是不是说明 egg 无法进行动态获取配置,来配置数据库插件呢
顶顶顶,大佬们有啥解决方案吗?现在的想法是修改启动命令,类似如下:
node getApollo.js && egg-bin debug
node getApollo.js 负责第一次获取apollo配置,并且写入json文件中,再在 config.*.js 中读取json配置添加配置,解决config提早加载的问题
@ddzyan 实在不行你把egg-sequelize 复制一遍改成新的hook写法,推迟到更后的生命周期再加载数据库
@AnzerWall 这样的话我觉得我上面的改动方法会好点。 只是我原本的目的是做一个 egg-apollo 插件,不应该涉及到其他插件的修改。主要想了解下egg是否支持异步获取配置,并且在插件启动前进行更新。
这是我提交的issue https://github.com/eggjs/egg/issues/4113
这个问题是不是无解了呢?或者说EGG暂时没考虑使用apollo获取动态配置(例如数据库连接配置)呢
@ddzyan 如果要使用 apollo 的热更新的话,就是无解的,至少现在是
因为热更新的时候可能需要重启 sequelize、redis… 这种骚操作在生产就是坟头蹦迪 233
如果只是将 apollo 作为一个存配置的地方,启动之前直接跑个脚本去拉一下就行
@xiedacon 还是有临时解的,在 agent 里面 appollo 拉配置,然后写文件,在 worker 这边 require
@atian25 写文件当然是可以的,我说的是 “热更新”,指程序跑到一半突然更新
我看他那个插件里面是这么写的,,
@xiedacon 那需要对用到的插件都要做处理,支持重新建立连接。