apolloconfig / apollo-java

Apollo Java Clients
Apache License 2.0
40 stars 72 forks source link

apollo-client支持多appid拉取配置的功能 #66

Open TerryLam2010 opened 5 months ago

TerryLam2010 commented 5 months ago
  1. 背景 现在java apollo client 不支持多appid拉取配置数据. 在一个应用中确实存在需要拉取不同应用appid下配置数据。来减少配置的重复配置。 比如在一个整合层应用,需要用到多个appid下的多种业务配置,开关进行复用。

  2. 实现后的特征 (1)@JsonApolloValue,@ApolloConfigChangeListener 增加appid+name的属性,@Value保持原有使用. 如果不同appid/不同namespace 出现相同key,以加载config顺序最优先的值为准 (3)bootstrap 暂不支持 多appid的拉取 (4) @EnableApolloConfig 增加一个属性 mutipleConfig 可以放多个 @MutipleConfig ,属性有appId,多个namespace,以及对应的secret.
    使用者可以在注解@MutipleConfig上填写 SpringEl表达式,读取配置文件中的secret

  3. 实现方案 类需要增加appid (1) AbstractConfigFile,AbstractConfig 需要增加 appId 属性,其子类构造方法,都需要增加appId的传入。 (2) RepositoryChangeListener, onRepositoryChange 方法增加appId的传入。 (3)变更类 ConfigChange、ConfigChangeEvent、ConfigFileChangeEvent 增加appId属性

    获取配置 (4)ConfigService 增加 getConfig(String appId,String namespace),保留 getConfig(String namespace) 读取原有app.id中的配置 (5) 增加一个@ApolloValue和对应的ApolloValueAnnotationProcessor (直接使用@JsonApolloValue 其实可以不加)

    初始化Config (6)DefaultApolloConfigRegistrarHelper增加解析@EnableApolloConfig中的@MutipleConfig, 组合appId+namespace,再传入PropertySourcesProcessor.addNamespaces(Map<String,List> namespaceMap), key为appid,value为 对应appId的namespace。 再传入PropertySourcesProcessor中initializePropertySources 可以根据appid+namespace 创建config (7) RemoteConfigRepository、LocalFileConfigRepository、RemoteConfigLongPollService 创建时传入appid+namespace,根据传入的appid+namespace 拉取配置 (8)Config 的创建,DefaultConfigManager、ConfigFactory增加appId创建,这点关联(7) (9) 进行初始化时,若@EnableApolloConfig没有配置appid,默认读取app.id的,包括bootstrap 初始化时 进行的Config拉取。

    多appid 和secret的配置 (10) 配置文件中增加 多appid。拆解后,放入一个环境变量中进行管理。

    配置刷新 (11) AutoUpdateConfigChangeListener 无改变。在考虑是否处理不同namespace下同key覆盖的情况,若兼容该情况,则现有的值不能放入properties中被管理。改造较大。

nobodyiam commented 5 months ago

(4) @EnableApolloConfig 增加一个属性 mutipleConfig 可以放多个 @MutipleConfig ,属性有appId,多个namespace,以及对应的secret.

这个编程界面会是怎么样的,可以写一个伪代码示例吗?

另外,@ApolloConfig 应该也需要修改?

TerryLam2010 commented 5 months ago

1.是的@ApolloConfig 也是需要修改增加一个appId的,当时有比较多的类也是需要增加appid的,就不一一列了。

  1. EnableApolloConfig 的伪代码。secret是非必填的,有默认值。 @EnableApolloConfig(value = {"application","kafka"},multipleConfig = {@MultipleConfig(appId = "shop",namespaces = {"shop-common","shop2-common"},secret = "${apollo.shop.secret}"), @MultipleConfig(appId = "pay",namespaces = {"pay-common"},secret = "${apollo.pay.secret}")})
nobodyiam commented 4 months ago

看起来 @MultipleConfig@ApolloConfig 非常类似,@EnableApolloConfig 中可以嵌套使用 @ApolloConfig 作为 multiple config 吗?

TerryLam2010 commented 4 months ago

@ApolloConfig 我看代码是你们用来进行config注入的。而@MultipleConfig 是配套在@EnableApolloConfig中 作为多appid的配置。如果@ApolloConfig 用于 config的注入,也用于@EnableApolloConfig 中多appid的配置,会不会太混淆了?是不是含义保持单一比较好呢?

另外还有个问题,现在的设计,注解部分,如果不同namespace存在相同key名,将会以加载顺序优先的config的值进行返回。我在想能不能按appid+namespace 分组获取到对应的config,再取值对注解的值进行反射。 我在想能不能打破的你原来的设计,AutoUpdateConfigChangeListener的resolvePropertyValue,直接解析SpringEl,然后跟根据appid+namespace 获取到对应的config,就设置值。 现有代码如下:

    // value will never be null, as @Value and @ApolloJsonValue will not allow that
    Object value = placeholderHelper
        .resolvePropertyValue(beanFactory, springValue.getBeanName(), springValue.getPlaceholder());  

想改成

AutoUpdateConfigChangeListener.class
private Object resolvePropertyValue(SpringValue springValue) {
   // 假装有appid+namespace了
    Config config = getConfig(appid,namespace)
    Object value = placeholderHelper
        .resolvePropertyValue(beanFactory, springValue.getBeanName(), springValue.getPlaceholder(),config); 
   }

PlaceholderHelper.class
  public Object resolvePropertyValue(ConfigurableBeanFactory beanFactory, String beanName, String placeholder,Config config) {
    // resolve string value  改动点在这下面两行。
    PlaceholderValue placeholderValue= resolveSpringEl(placeholder);
    String strVal = config.getProperty(placeholderValue.getKey(),placeholderValue.getDefaultValue());

    BeanDefinition bd = (beanFactory.containsBean(beanName) ? beanFactory
        .getMergedBeanDefinition(beanName) : null);

    // resolve expressions like "#{systemProperties.myProp}"
    return evaluateBeanDefinitionString(beanFactory, strVal, bd);
  }
nobodyiam commented 4 months ago

@ApolloConfig 我看代码是你们用来进行config注入的。而@MultipleConfig 是配套在@EnableApolloConfig中 作为多appid的配置。如果@ApolloConfig 用于 config的注入,也用于@EnableApolloConfig 中多appid的配置,会不会太混淆了?是不是含义保持单一比较好呢?

从含义上而言其实差不多,都是指定 appid/namespace 来注入配置。@EnableApolloConfig 是注入到 spring 的 property sources 中,@ApolloConfig 是注入到某个 field 中。

另外还有个问题,现在的设计,注解部分,如果不同namespace存在相同key名,将会以加载顺序优先的config的值进行返回。我在想能不能按appid+namespace 分组获取到对应的config,再取值对注解的值进行反射。

这个是为了适配 spring 的 property source 体系。如果要根据 appid+namespace 获取值的话就是完全不同的用法了,比如提供一个不同于 @Value 的注解。

TerryLam2010 commented 4 months ago

从含义上而言其实差不多,都是指定 appid/namespace 来注入配置。@EnableApolloConfig 是注入到 spring 的 property sources 中,@ApolloConfig 是注入到某个 field 中。

如果 @ApolloConfig 作为@EnableApolloConfig的multiple部分,是需要增加secret字段,但是觉得这个注解本来是是注入到某个 field的,增加secret还是怪怪的。感觉还是增加一个新注解好点的样子?

这个是为了适配 spring 的 property source 体系。如果要根据 appid+namespace 获取值的话就是完全不同的用法了,比如提供一个不同于 @Value 的注解。

是的,@Value属于Spring体系,要适配property source 才行。是需要提供一个新的注解代替。例如暂定一个 @ApolloValue

新提议: 另外@ApolloConfig可以提供一种新的含义,配置在类上,作为类里@ApolloValue,@ApolloJsonValue等注解的默认appid+namespace

 @ApolloConfig(appid="shop",namespace="shop-common")
 public class SystemConfig {

 @ApolloValue("${shop.name:''}")
 public static String shopName;

 @ApolloJsonValue("${shop.desc:''}")
 public static ShopDesc shopDesc;
 }

最后一个问题,能不能提供一个及时沟通的渠道和联系方式。这个issue还是有点慢。哈哈

nobodyiam commented 4 months ago

我觉得可以分成两步来做

  1. 增加多 appid 支持 这个问题定义比较明确

  2. 增加 @ApolloValue 这个可以放在后面讨论下,因为本质上而言和多 appid 无关,例如同一个 key 在多个 namespace 也会出现,之前也有人提出要做,不过当时看下来场景比较有限

TerryLam2010 commented 4 months ago

ok.先用回property source来适配各种,只做一个多appid的拉取。重复的key,走回原有逻辑。后续提交pr给你

stale[bot] commented 3 months ago

This issue has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in 7 days unless it is tagged "help wanted" or other activity occurs. Thank you for your contributions.

Rawven commented 2 months ago

When will the PR for this issue be merged? Because the merge of this PR will have an impact on another PR(https://github.com/apolloconfig/apollo-java/pull/74) I submitted, I need to make some adaptations, which is very important to me😀, thanks

nobodyiam commented 2 months ago

@Rawven I think it might take some time as it's a major change and needs some time to review.