|
本帖最后由 chaomeili 于 2020-12-23 10:50 编辑
当然你也可以在上面加一些性能上的优化哈,特别是加载 yaml 文件的部分。除了读取 yaml 配置文件的内容外,里面还通过 object-hash 来计算了配置的 revision,方便客户端来检查配置数据的版本更新。
提供统一的客户端 library
主体设计和实现就是上面说的这些内容了。不过,还有一项工作很重要,就是提供统一的客户端 library。当大家使用同样的客户端 library 来读取配置的时候,配置管理的坑儿才能算真正占好,后面才方便替换配置管理服务的技术方案。
library 设计
首先说一下这个 library 的接口设计吧
提供一个 get 方法,注意:
参数里面应该是一个 path,准确的说应该是一个 property path
这个方法应该是 同步执行 的,所以下面我提供了一个 sync 方法,专门用来同步配置数据
假设完整的配置数据是这样的:
{
"mysql": {
"host": "111.111.11.11",
"port": 3306,
"username": "root",
"password": "123456"
},
"redis": {
"host": "111.111.11.12",
"port": 6379
},
"wechat": {
"appId": "wx888888888"
},
"secret": "foobar"
}
|
那么通过 get 方法应该能够做到下面这些事情:
config.get("mysql")
// => {"host": "111.111.11.11", "port": 3306, ...}
config.get("wechat.appId")
// => "wx888888888"
config.get()
// => {"mysql": {...}, "wechat": {...}, ...}
|
也就是说,大家可以通过 get 方法灵活的获取到配置数据的某一部分。这块我们使用了 object-path 这个模块。
config.sync(host, profile, token) |
提供一个 sync 方法,用来初始话和轮训同步配置数据
config.on(event, listener) |
应该提供事件回调接口,用来检测是否有数据发生变化,这个接口在 Node.js 服务中有一定用处,其他的同步的技术框架应该就不需要了。
最后,应该有一个 mock 方法,方便支持自动化测试
一些补充内容
补充一下主要的实现代码,供大家参考:
const EventEmitter = require('events').EventEmitter;
const objectPath = require('object-path');
class Config {
constructor(interval) {
this.interval = interval || 5000;
this.emitter = new EventEmitter();
}
sync(host, profile, token) {
this.host = host;
this.profile = profile;
this.token = token;
this.data = loadConfigSync(); // 首先同步获取配置数据
setTimeOut(() => this.watch(), this.interval); // 之后,定时轮训数据
}
get(path) {
return objectPath.get(this.data.config, path);
}
loadConfigSync() {
// 这部分代码就先省略了~
}
async loadConfigAsync() {
// 这部分代码就先省略了~
}
async watch() {
const result = await this.loadConfigAsync();
if (result.revision !== this.data.revision) {
this.data = result;
this.emitter.emit('update', this.data.config);
}
setTimeout(() => this.watch(), this.interval);
}
}
module.exports = new Config();
使用客户端 library 的一般套路:
// server.js
const config = require('config-module-name');
// 1. 调用 sync 方法加载配置
config.sync(process.env.CONFIG_HOST, process.env.CONFIG_PROFILE, process.env.CONFIG_TOKEN);
// 2. 启动实际项目的 WebServer
const server = new WebServer();
server.serve();
|
|
|