分享基于zookeeper分布式配置中心的util 讨论一下
打算原有source code中静态配置为主, 一些动态配置放在配置中心为辅. 写的这个util, 项目启动时拉取一次配置, cache在内存中, 当zookeeper中当前项目的配置发生变化时可主动推送, 更新cache.
/* ******************************************************************
* dynamic config on the basis of zookeeper config center
****************************************************************** */
import ZK, { Event } from 'node-zookeeper-client'
import { promisify } from 'util'
import config from '../config'
const zookeeper = ZK.createClient(config.ZOO_KEEPER)
zookeeper.once('connected', getAllConfigs)
zookeeper.connect()
const getChildren = promisify(zookeeper.getChildren).bind(zookeeper)
const getData = promisify(zookeeper.getData).bind(zookeeper)
const path = `/config/${config.API_NAME}/${process.env.NODE_ENV}`
/**
* local config cache, change on it is only triggered by config center
*/
const dynconfig = new Map<string, string>()
/**
* fetch keys of all config nodes
* start watching on config nodes creation or removal
*/
async function getAllConfigs() {
const localKeys = [...dynconfig.keys()]
const children = await getChildren(
path,
(event: Event) => {
console.log('[config center] => [%s] %s', getAllConfigs.name, event.name)
getAllConfigs()
},
)
console.log('[config center] => below are latest config items fetched')
await Promise.all(children.sort().map((key: string) => {
const isNewKey = !localKeys.includes(key)
return getConfig(key, isNewKey)
}))
// remove deleted config node from local config cache
localKeys.forEach(key => {
if (!children.includes(key)) {
dynconfig.delete(key)
}
})
}
/**
* fetch value of a config node
* start watching on config node value update
*/
async function getConfig(key: string, addWatcher?: boolean) {
const rawValue = await getData(
`${path}/${key}`,
// register a watcher only once
!addWatcher ? undefined : (event: Event) => {
console.log('[config center] => [%s] %s', getConfig.name, event.name)
if (event.type !== Event.NODE_DELETED) {
getConfig(key, true)
}
},
)
const value = rawValue.toString('utf8')
console.log(' %s: %s', key, value)
dynconfig.set(key, value)
}
export default dynconfig
下面是些相应日志