问题

服务重启后,服务中的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
    D-Chat_20251120222348
  • 在isNotMatchConfigName方法中过滤运营模板唯一性规则值是否匹配,过滤掉不匹配的配置数据
    D-Chat_20251120222714

问题点

  • 在调用 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");