Apollo介绍
Apollo(阿波罗)是一款可靠的分布式配置管理中心,诞生于携程框架研发部,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。
服务端基于Spring Boot和Spring Cloud开发,打包后可以直接运行,不需要额外安装Tomcat等应用容器。
Java客户端不依赖任何框架,能够运行于所有Java运行时环境,同时对Spring/Spring Boot环境也有较好的支持。
Apollo核心概念
- 项目(应用)
这个很好理解,就是实际使用Apollo配置中心的应用,该应用一般指的就是我们自己的微服务工程。通过引入Apollo客户端,就可以在运行时去配置中心获取对应的配置
关键字:appId
- environment (环境)
配置对应的环境,Apollo客户端在运行时需要知道当前应用处于哪个环境,从而可以去获取应用的配置
关键字:env
- cluster (集群)
一个应用下不同实例的分组,比如典型的可以按照数据中心进行划分,把上海机房的应用实例分为一个集群,把北京机房的应用实例分为另一个集群。
关键字:cluster
- namespace (命名空间)
一个应用下不同配置的分组,可以简单地把namespace类比为文件,不同类型的配置存放在不同的文件中,如数据库配置文件,RPC配置文件,应用自身的配置文件等
关键字:namespaces
Apollo特性
-
统一管理不同环境、不同集群的配置
-
配置修改实时生效(热发布)
- 用户在Apollo修改完配置并发布后,客户端能实时(1秒)接收到最新的配置,并通知到应用程序
-
版本发布管理
- 所有的配置发布都有版本概念,从而可以方便地支持配置的回滚
-
灰度发布
- 支持配置的灰度发布,比如点了发布后,只对部分应用实例生效,等观察一段时间没问题后再推给所有应用实例
-
权限管理、发布审核、操作审计
- 应用和配置的管理都有完善的权限管理机制,对配置的管理还分为了编辑和发布两个环节,从而减少人为的错误。
- 所有的操作都有审计日志,可以方便地追踪问题
-
客户端配置信息监控
- 可以在界面上方便地看到配置在被哪些实例使用
Apollo基础模型
Apollo的基础模型:
- 用户在配置中心对配置进行修改并发布
- 配置中心通知Apollo客户端有配置更新
- Apollo客户端从配置中心拉取最新的配置、更新本地配置并通知到应用
Apollo总体设计
- Config Service提供配置的读取、推送等功能,服务对象是Apollo客户端
- 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、错误重试
- 为了简化部署,我们实际上会把Config Service、Eureka和Meta Server三个逻辑角色部署在同一个JVM进程中
Apollo安装
环境
- JDK1.8+
- Mysql5.6.5+
- 数据库导入
ApolloPortalDB和ApolloConfigDB - 配置数据库连接信息
搭建Apollo服务端
Quick Start脚本会在本地启动3个服务,分别使用8070, 8080, 8090端口,请确保这3个端口当前没有被使用。
执行启动脚本
./demo.sh start
访问
erueka
Apollo
Springboot整合Apollo
新增应用
配置说明:
部门:选择应用所在的部门。(想自定义部门,参照官方文档,这里就选择样例)
应用AppId:用来标识应用身份的唯一id,格式为string,需要和客户端。application.properties中配置的app.id对应。
应用名称:应用名,仅用于界面展示。
应用负责人:选择的人默认会成为该项目的管理员,具备项目权限管理、集群创建、Namespace创建等权限。
添加配置
Springboot项目搭建
案例github地址:github.com/Junlogz/spr…
pom.xml
添加 Apollo 客户端的依赖,主要的就是apollo依赖
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>1.4.0</version>
</dependency>
application.yml
server:
port: 9090
app:
id: springboot-test-apollo
apollo:
meta: http://127.0.0.1:8080
bootstrap:
enabled: true
eagerLoad:
enabled: true
配置说明:
app.id :AppId是应用的身份信息,是配置中心获取配置的一个重要信息。
apollo.bootstrap.enabled:在应用启动阶段,向Spring容器注入被托管的application.properties文件的配置信息。
apollo.bootstrap.eagerLoad.enabled:将Apollo配置加载提到初始化日志系统之前。
TestController.java
@RestController
public class TestController {
private static Logger log = LoggerFactory.getLogger( TestController.class );
@Value( "${date.value}" )
String dateValue;
@GetMapping("test")
public String test() {
return "打印配置中心的 dateValue 值: "+ dateValue;
}
@GetMapping("test1")
public void test1() {
log.info("当前配置中心的 dateValue 值 = {}",dateValue);
}
}
启动类
@SpringBootApplication
@EnableApolloConfig
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}
需要添加@EnableApolloConfig注解
测试
分别两次请求,中间修改一次配置文件
动态修改日志级别
yml中添加配置
#这里说明在将该项目 com目录下的日志,都采用info模式输出
logging:
level:
com: info
我们来思考有没有这么一种需求,我们在线上的日志级别一般是INFO级别的,主要记录业务操作或者错误的日志。那么这个时候当线上环境出现问题希望输出DEBUG
日志信息辅助排查的时候怎么办呢?
如果以前,我们可以会修改配置文件,重新打包然后上传重启线上环境,以前确实是这么做的。通过Apollo配置中心我们可以实现不用重启项目,就可以实现让日志
基本从INFO变成DEBUG。下面我们来演示一番。
在项目启动之前,我在application.yml配置了日志级别是info模式。我们来请求下面接口验证下。
可以很明显的看出,控制台只打印info级别以上的日志,并没有打印debug日志。
现在我们要做的是将打印日志级别不在交给application.yml而是交给apollo来配置。这里其实要做两步:
1)、在apollo配置一条日志数据。
2)、通过监听配置的变化,来达到热更新的效果。
配置类
@Configuration
public class LoggerConfig {
private static final Logger logger = LoggerFactory.getLogger(LoggerConfig.class);
private static final String LOGGER_TAG = "logging.level.";
@Autowired
private LoggingSystem loggingSystem;
@ApolloConfig
private Config config;
@ApolloConfigChangeListener
private void configChangeListter(ConfigChangeEvent changeEvent) {
refreshLoggingLevels();
}
@PostConstruct
private void refreshLoggingLevels() {
Set<String> keyNames = config.getPropertyNames();
for (String key : keyNames) {
if (StringUtils.containsIgnoreCase(key, LOGGER_TAG)) {
String strLevel = config.getProperty(key, "info");
LogLevel level = LogLevel.valueOf(strLevel.toUpperCase());
loggingSystem.setLogLevel(key.replace(LOGGER_TAG, ""), level);
logger.info("{}:{}", key, strLevel);
}
}
}
}
解析:
@ApolloConfig注解:将Apollo服务端的中的配置注入这个类中。
@ApolloConfigChangeListener注解:监听配置中心配置的更新事件,若该事件发生,则调用refreshLoggingLevels方法,处理该事件。
ConfigChangeEvent参数:可以获取被修改配置项的key集合,以及被修改配置项的新值、旧值和修改类型等信息。
从上面可以看出,通过@PostConstruct 项目启动的时候就去获取apollo的日志级别去覆盖application.yml日志级别。我在apollo配置中心,新增加一条日志配置。
把日志级别设置error,那么在项目启动的时候,因为PostConstruct注解的原因,所以会去执行一次refreshLoggingLevels方法,把当前日志级别改成error。
测试
重启项目,重新请求接口
再修改日志级别为debug,再请求接口