Apollo 配置中心
1 概念
- AppId:用来标识应用身份的唯一id,格式为string,需要和客户端app.properties中配置的app.id对应
- 应用名称:应用名,仅用于界面展示
- 集群:在有些特殊情况下,应用有需求对不同的集群做不同的配置,比如部署在A机房的应用连接的es服务器地址和部署在B机房的应用连接的es服务器地址不一样。在这种情况下,可以通过在Apollo创建不同的集群来解决。
- namespace:Namespace是配置项的集合,类似于一个配置文件的概念。
- 私有:private权限的Namespace,只能被所属的应用获取到。一个应用尝试获取其它应用private的Namespace,Apollo会报“404”异常。
- 公共:public权限的Namespace,能被任何应用获取。
- 关联:继承类型
- 灰度发布:
- 对于一些对程序有比较大影响的配置,可以先在一个或者多个实例生效,观察一段时间没问题后再全量发布配置。
- 对于一些需要调优的配置参数,可以通过灰度发布功能来实现A/B测试。可以在不同的机器上应用不同的配置,不断调整、测评一段时间后找出较优的配置再全量发布配置。
- 热发布:用户在Apollo修改完配置并发布后,客户端能实时(1秒)接收到最新的配置,并通知到应用程序。
2 架构
- 集群部署参考(比较简洁):
2.1 服务端架构
- 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 客户端架构
- 客户端和服务端保持了一个长连接,从而能第一时间获得配置更新的推送。(通过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的逻辑:
- Apollo 配置了日志级别 debug
- 有一个线程一直在输出 debug、info、warn、error 4个级别的日志,可以从控制台中看到。
- 在 Apollo 中修改日志级别为 warn,随后可以立即观察到控制台只输出 warn、error两个级别的日志。