Apollo 配置中心

1 概念

  • AppId:用来标识应用身份的唯一id,格式为string,需要和客户端app.properties中配置的app.id对应
  • 应用名称:应用名,仅用于界面展示
  • 集群:在有些特殊情况下,应用有需求对不同的集群做不同的配置,比如部署在A机房的应用连接的es服务器地址和部署在B机房的应用连接的es服务器地址不一样。在这种情况下,可以通过在Apollo创建不同的集群来解决。
  • namespace:Namespace是配置项的集合,类似于一个配置文件的概念。
  • 私有:private权限的Namespace,只能被所属的应用获取到。一个应用尝试获取其它应用private的Namespace,Apollo会报“404”异常。
  • 公共:public权限的Namespace,能被任何应用获取。
  • 关联:继承类型
  • 灰度发布:
  1. 对于一些对程序有比较大影响的配置,可以先在一个或者多个实例生效,观察一段时间没问题后再全量发布配置。
  2. 对于一些需要调优的配置参数,可以通过灰度发布功能来实现A/B测试。可以在不同的机器上应用不同的配置,不断调整、测评一段时间后找出较优的配置再全量发布配置。
  • 热发布:用户在Apollo修改完配置并发布后,客户端能实时(1秒)接收到最新的配置,并通知到应用程序。

2 架构

  • 集群部署参考(比较简洁):

2.1 服务端架构

Apollo如何批量复制namespace apollo namespace_java

  • Config Service 提供配置的读取、推送等功能,服务对象是 Apollo client
  • Admin Service 提供配置的修改、发布等功能,服务对象是 Apollo Portal(管理界面)
  • Config Service 和 Admin Service 都是多实例、无状态部署,所以需要将自己注册到Eureka中并保持心跳
  • 在Eureka之上架了一层 Meta Server 用于封装Eureka的服务发现接口
  • Client通过域名访问 Meta Server 获取 Config Service 服务列表(IP+Port),而后直接通过IP+Port访问服务,同时在Client侧会做load balance、错误重试
  • Portal通过域名访问 Meta Server 获取 Admin Service 服务列表(IP+Port),而后直接通过IP+Port访问服务,同时在Portal侧会做load balance、错误重试

2.2 客户端架构

Apollo如何批量复制namespace apollo namespace_客户端_02

  • 客户端和服务端保持了一个长连接,从而能第一时间获得配置更新的推送。(通过Http Long Polling实现)
  • 客户端还会定时从Apollo配置中心服务端拉取应用的最新配置。(这是一个 fallback 机制,防止推送机制失效)
  • 最新配置在内存缓存
  • 配置文件在文件系统缓存(遇到服务不可用时从本地恢复)

3 使用

3.1 相关注解、配置

  • @EnableApolloConfig
  • @ApolloConfig
app:
  id: spring-cloud-logger #appId
apollo:
  meta: http://localhost:8080

3.2 热发布修改日志级别 Demo (Spring Cloud)

@Service
public class LoggerLevelRefresher implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    @ApolloConfig
    private Config config;

    @PostConstruct
    private void initialize() {
        refreshLoggingLevels(config.getPropertyNames());
    }

    @ApolloConfigChangeListener(interestedKeyPrefixes = {"logging.level."})
    private void onChange(ConfigChangeEvent changeEvent) {
        refreshLoggingLevels(changeEvent.changedKeys());
    }

    private void refreshLoggingLevels(Set<String> changedKeys) {
        System.out.println("Refreshing logging levels");
        System.out.println(changedKeys);
        /**
         * refresh logging levels
         * @see org.springframework.cloud.logging.LoggingRebinder#onApplicationEvent
         */
        this.applicationContext.publishEvent(new EnvironmentChangeEvent(changedKeys));

        System.out.println("Logging levels refreshed");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    
}

Demo的逻辑:

  1. Apollo 配置了日志级别 debug
  2. 有一个线程一直在输出 debug、info、warn、error 4个级别的日志,可以从控制台中看到。
  3. 在 Apollo 中修改日志级别为 warn,随后可以立即观察到控制台只输出 warn、error两个级别的日志。