disconf可以随时同步配置文件的变化到仓库中。也就是说,配置文件中的参数发生了变化,应用系统会随时获取到最新的参数值。这依靠的是watch+callback机制。
Watch
第一次扫描时,在开启disconf的情况下,会在zk上建立一个代表配置文件的临时结点,monitorPath形如”/disconf/应用名版本号环境/file/sys-config.properties”。然后便监控这个节点。
/**
* 监控路径,监控前会事先创建路径,并且会新建一个自己的Temp子结点
*/
public void watchPath(DisconfCoreProcessor disconfCoreMgr, DisConfCommonModel disConfCommonModel, String keyName,
DisConfigTypeEnum disConfigTypeEnum, String value) throws Exception {
// 新建
String monitorPath = makeMonitorPath(disConfigTypeEnum, disConfCommonModel, keyName, value);
// 进行监控
NodeWatcher nodeWatcher =
new NodeWatcher(disconfCoreMgr, monitorPath, keyName, disConfigTypeEnum, new DisconfSysUpdateCallback(),
debug);
nodeWatcher.monitorMaster();
}
Callback
当结点更新时,会触发一个WatchedEvent,系统会自动调用回调函数。
调用回调函数的源码见com.baidu.disconf.client.watch.inner.NodeWatcher,如下:
/**
* 回调函数
*/
@Override
public void process(WatchedEvent event) {
//
// 结点更新时
//
if (event.getType() == EventType.NodeDataChanged) {
try {
LOGGER.info("============GOT UPDATE EVENT " + event.toString() + ": (" + monitorPath + "," + keyName
+ "," + disConfigTypeEnum.getModelName() + ")======================");
// 调用回调函数, 回调函数里会重新进行监控
callback();
} catch (Exception e) {
LOGGER.error("monitor node exception. " + monitorPath, e);
}
}
....
}
/**
*
*/
private void callback() {
try {
// 调用回调函数, 回调函数里会重新进行监控
try {
disconfSysUpdateCallback.reload(disconfCoreMgr, disConfigTypeEnum, keyName);
} catch (Exception e) {
LOGGER.error(e.toString(), e);
}
} catch (Exception e) {
LOGGER.error("monitor node exception. " + monitorPath, e);
}
}
回调函数主要做了两件事情:
(1)更新配置数据仓库(updateOneConfFile方法),再更新实例(inject2OneConf方法)
(2)调用用户的回调函数列表
回调函数的源码见com.baidu.disconf.client.core.processor.impl.DisconfFileCoreProcessorImpl,如下:
/**
* 更新消息: 某个配置文件 + 回调
*/
@Override
public void updateOneConfAndCallback(String key) throws Exception {
// 更新 配置
updateOneConf(key);
// 回调
invokeOneConfCallback(key);
}
/**
* 更新消息:某个配置文件
*/
private void updateOneConf(String fileName) throws Exception {
DisconfCenterFile disconfCenterFile = (DisconfCenterFile) disconfStoreProcessor.getConfData(fileName);
if (disconfCenterFile != null) {
// 更新仓库
updateOneConfFile(fileName, disconfCenterFile, true);
// 更新实例
inject2OneConf(fileName, disconfCenterFile);
}
}
@Override
public void invokeOneConfCallback(String key) throws Exception {
// 回调
DisconfCoreProcessUtils.callOneConf(disconfStoreProcessor, key);
callUpdatePipeline(key);
}
这样,修改的配置文件就及时得到了更新。