文章目录

  • 1. 前提
  • 2. 基本思想
  • 3. 实施步骤
  • 4. 那些修改以后要重新加载bean的配置自动更新的处理
  • 5. 注意事项
  • 6. 后续改进


Apollo本身就支持环境隔离,你可以配置不同的environment来实现,当然你也可以给不同环境搭建不同的apollo服务(如果你资源充足的话)。
但是这篇文章讲的是在资源有限的情况下如何实现环境隔离。

1. 前提

该方案的前提是:

  1. 你只有一个test的apollo服务和一个prod的apollo服务。
  2. test和prod上都默认只有DEV的environment。这个现状目前你可能没能力修改。
  3. 你需要用test环境来支持dev,test,beat三套环境的配置,并且每个环境只加载自己的环境配置即可,不需要加载所有环境的配置。

2. 基本思想

利用现有的公司的test环境,将项目的dev,beta和test环境配置都放在上面,即给不同的环境创建不同的namespace,如图

apollo怎么将私有namespace改为公共_加载

3. 实施步骤

apollo怎么将私有namespace改为公共_java_02

  1. 在application.yml配置文件配置appid。
  2. 将beta、dev、release、test对应的配置文件的配置转移到apollo配置中心。
  3. 将beta、dev、release、test对应的配置文件的配置删除,分别加入配置:
apollo:
  bootstrap:
    enabled: true
    # 当前环境对应的apollo中的namespace
    namespaces: tiku-ziliao-dev.yml
    # 当前环境对应的meta-server地址,该方案中,dev、test、beta环境均为http://test-apollo-meta.jarry.com,prod为http://apollo-meta.jarry.com
  meta: http://test-apollo-meta.jarry.com

至此,引入完成!

4. 那些修改以后要重新加载bean的配置自动更新的处理

这类配置有mysql连接相关配置、redis连接相关配置、@ConfigurationProperties引入的配置等。

对于这种配置需要使用Apollo配置监听器,具体到该方案,需要不同环境监听不同的配置文件。

  • @ApolloConfigChangeListener

该注解可以制指定要监听的namespace,但是不能实现根据不同的环境来监听不同的配置文件。

  • Apollo原生API

该API可以根据指定的namespace获取其对用的Config对象,给Config对象添加事件监听即可,代码如下:

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
 
/**
 * @author xujian03
 * @date 2020/3/12 15:18
 * @description
 */
@Component
@ConfigurationProperties(prefix = "my.user")
@RefreshScope
public class UserInfoConfig {
    private String name;
    private String nick;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getNick() {
        return nick;
    }
 
    public void setNick(String nick) {
        this.nick = nick;
    }
 
    @Override
    public String toString() {
        return "UserInfoConfig{" +
                "name='" + name + '\'' +
                ", nick='" + nick + '\'' +
                '}';
    }
}
 
 
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.scope.refresh.RefreshScope;
import org.springframework.stereotype.Component;
 
import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.Set;
 
/**
 * @author xujian03
 * @date 2020/3/12 15:21
 * @description
 */
@Component
public class SpringBootApolloRefreshConfig{
    @Autowired
    private UserInfoConfig userInfoConfig;
 
    @Autowired
    private RefreshScope refreshScope;
    //指定的环境
    @Value("${spring.profiles.active}")
    private String env;
    //配置文件前缀
    private static final String NAMESPACE_PREFIX="xxx-";
    //配置文件后缀
    private static final String NAMESPACE_SUFFIX=".yml";
 
    @PostConstruct
    public void init() {
        Config config = ConfigService.getConfig(NAMESPACE_PREFIX+env+NAMESPACE_SUFFIX);
        Set<String> prefix = new HashSet<>();
        prefix.add("my.user.");
        //该方法有三个参数,第一个参数是具体的listener,第二个参数是感兴趣的key,第三个参数是感兴趣的key的前缀
        config.addChangeListener(changeEvent -> {
            System.out.println("before refresh "+userInfoConfig.toString());
            //重新加载指定bean
            refreshScope.refresh("userInfoConfig");
            System.out.println("after refresh "+userInfoConfig.toString());
        },null,prefix);
    }
}

5. 注意事项

  1. spring.main.allow-bean-definition-overriding 这个配置放在apollo配置中心的时候不生效

解决方法:

1) 将spring.main.allow-bean-definition-overriding=true放到application.yml配置文件;

2) Apollo的客户端配置加上apollo.bootstrap.eagerLoad.enabled=true,如

apollo:
  bootstrap:
    enabled: true
    # 当前环境对应的apollo中的namespace
    namespaces: xxx.yml
    # 让apollo配置更早加载
    eagerLoad:
      enabled: true
    # 当前环境对应的meta-server地址
  meta: http://test-apollo-meta.com

6. 后续改进



//配置文件前缀
private static final String NAMESPACE_PREFIX="tiku-ziliao-";
//配置文件后缀
private static final String NAMESPACE_SUFFIX=".yml";

这种前缀后缀可以放在配置文件里。

  1. 对于使用@ConfigurationProperties注解的bean,可以使用AOP自动加上listener。