问题
服务重启后,服务中的apollo配置数据丢失,单个编辑后可获取到编辑后的数据
apollo数据初始化代码
- 在服务启动的PostConstruct方法中执行process方法,并且不带configName
- 当配置出现变更时,只针对特定的configName进行初始化,调用process方法时configName有值
private void process(String configName) {
synchronized (LOCK) {
if (StringUtils.isBlank(configName)) {//No1
// 全量刷新
Condition condition = new Condition();
condition.with("__key", "value");//No3
Collection<Config> allConfigs = Apollo.getConfigsByNamespaceAndConditions(this.namespace(), condition).getAllConfigs();//No2
for (Config config : allConfigs) {
T obj = parseConfig(config);
if (obj != null) {
context.put(config.getConfigName(), obj);
}
}
} else {
// 单个变更
Config config = Apollo.getConfig(this.namespace(), configName);
T obj = parseConfig(config);
if (obj != null) {
context.put(config.getConfigName(), obj);
}
}
}
}
排查方案
- 在节点上对配置进行编辑
- 在本地 remote debug
- 当执行至No1时,将configName设置为空字符串
- 然后调用至No2
- 在Apollo.getConfigsByNamespaceAndConditions会调用getMatchConfigsByCondition(namespaceConfig, condition, configNameRules.value())方法
- 在该方法的buildConfigNameHashValues(configNameRules, condition)中对相应condition中的过滤条件,并且在apollo运营模板id规则中的字段进行hash

- 在isNotMatchConfigName方法中过滤运营模板唯一性规则值是否匹配,过滤掉不匹配的配置数据

问题点
- 在调用 Apollo.getConfigsByNamespaceAndConditions时如果不传condition会报错(return NamespaceConfig.createInvalidResult(namespace, "condition is null");)
- 故大家都会传一个condition(No3)
- 而key和value值都是随意写的
- 而本次巧就巧在模板中的唯一性校验字段就是key,所以就会去查询配置中key字段值为value的配置,查不到就不会初始化
- 看了代码 不传condition查不了,但是可以传个空condition,但是未验证,防止出现其它问题,暂停时调整condition的key
Condition condition = new Condition();
condition.with("__key", "value");