配置中心之Apollo

介绍

Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。

—— Apollo官方WIKI

gitHub:Apollo

特点

正是基于配置的特殊性,所以Apollo从设计之初就立志于成为一个有治理能力的配置发布平台,目前提供了以下的特性:

  • 统一管理不同环境、不同集群的配置
    • Apollo提供了一个统一界面集中式管理不同环境(environment)、不同集群(cluster)、不同命名空间(namespace)的配置。
    • 同一份代码部署在不同的集群,可以有不同的配置,比如zookeeper的地址等
    • 通过命名空间(namespace)可以很方便地支持多个不同应用共享同一份配置,同时还允许应用对共享的配置进行覆盖
  • 配置修改实时生效(热发布)
    • 用户在Apollo修改完配置并发布后,客户端能实时(1秒)接收到最新的配置,并通知到应用程序
  • 版本发布管理
    • 所有的配置发布都有版本概念,从而可以方便地支持配置的回滚
  • 灰度发布
    • 支持配置的灰度发布,比如点了发布后,只对部分应用实例生效,等观察一段时间没问题后再推给所有应用实例
  • 权限管理、发布审核、操作审计
    • 应用和配置的管理都有完善的权限管理机制,对配置的管理还分为了编辑和发布两个环节,从而减少人为的错误。
    • 所有的操作都有审计日志,可以方便地追踪问题
  • 客户端配置信息监控
    • 可以在界面上方便地看到配置在被哪些实例使用
  • 提供Java和.Net原生客户端
    • 提供了Java和.Net的原生客户端,方便应用集成
    • 支持Spring Placeholder, Annotation和Spring Boot的ConfigurationProperties,方便应用使用(需要Spring 3.1.1+)
    • 同时提供了Http接口,非Java和.Net应用也可以方便地使用
  • 提供开放平台API
    • Apollo自身提供了比较完善的统一配置管理界面,支持多环境、多数据中心配置管理、权限、流程治理等特性。不过Apollo出于通用性考虑,不会对配置的修改做过多限制,只要符合基本的格式就能保存,不会针对不同的配置值进行针对性的校验,如数据库用户名、密码,Redis服务地址等
    • 对于这类应用配置,Apollo支持应用方通过开放平台API在Apollo进行配置的修改和发布,并且具备完善的授权和权限控制
  • 部署简单
    • 配置中心作为基础服务,可用性要求非常高,这就要求Apollo对外部依赖尽可能地少
    • 目前唯一的外部依赖是MySQL,所以部署非常简单,只要安装好Java和MySQL就可以让Apollo跑起来
    • Apollo还提供了打包脚本,一键就可以生成所有需要的安装包,并且支持自定义运行时参数

快速开始

确保 java version 8+

下载快速开始项目

下载:https://github.com/nobodyiam/apollo-build-scripts.git

下到本地后解压如下:

image-20200512113925813

启动本地服务端

使用 gitbash 在当前目录(上图)执行 demo.sh

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
s-master
$ ./demo.sh start
Windows new JAVA_HOME is: /d/Java/jdk1.8.0_144
version : 1.8.0_144
==== starting service ====
Service logging file is ./service/apollo-service.log
Started [18080]
Waiting for config service startup......
Config service started. You may visit http://localhost:8080 for service status now!
Waiting for admin service startup
Admin service started
==== starting portal ====
Portal logging file is ./portal/apollo-portal.log
Started [19772]
Waiting for portal startup...
Portal started. You can visit http://localhost:8070 now!

wuzhiyong@DESKTOP-SAUA6M1 MINGW64 /e/迅雷下载/apollo配置中心/apollo-build-scripts-master
$

在 Windows 下执行可能会出现类似提示:

1
Java version is , please make sure java 1.8+ is in the path

本人这里折腾了些时间,重新下载配置更高版本的jdk,修改调试 demo.sh 都不行,后来在这篇博客(点这里)得到解决。 问题原因是 apollo 读 java 地址路径上不能有空格。我的 jdk 是放在 Program Files 下,这里有个空格。后面 把 jdk 移到其它位置,并重新配置好环境变量就可以了。

登录服务端控制台

打开地址:

http://localhost:8070

image-20200512115251752

输入 用户名:apollo 密码 admin

image-20200512115334476

点击 SampleApp 项目后可看到类似下面的内容

image-20200513113702191

配置客户端

在 springboot 项目中添加客户端依赖

1
2
3
4
5
 <dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>1.1.0</version>
</dependency>

启动类设置环境 (下下来的快速开始项目 本地启动只有一个环境,我测试的时候不加这段也可以)

1
2
3
4
5
6
7
8
@SpringBootApplication
public class SpringcloudZuulFileDemoApplication {

public static void main(String[] args) {
System.setProperty("env","DEV");
SpringApplication.run(SpringcloudZuulFileDemoApplication.class, args);
}
}

properties中配置

1
2
3
4
apollo.bootstrap.enabled=true
app.id=SampleApp
apollo.meta=http://localhost:8080
apollo.bootstrap.namespaces=application

添加一个属性类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class TestJavaConfigBean {
@Value("${timeout:100}")
private int timeout;
private int batch;

@Value("${batch:200}")
public void setBatch(int batch) {
this.batch = batch;
}

public int getTimeout() {
return timeout;
}

public int getBatch() {
return batch;
}
}

配置

1
2
3
4
5
6
7
8
9
@Configuration
@EnableApolloConfig
public class AppConfig {
@Bean
public TestJavaConfigBean javaConfigBean() {
return new TestJavaConfigBean();
}
}

控制器测试

1
2
3
4
5
6
7
8
9
10
11
12
@RestController
public class Controller {

@Autowired
TestJavaConfigBean testJavaConfigBean;
@GetMapping("get/config")
public Object test(){
return "timeout:"+testJavaConfigBean.getTimeout()
+"batch"
+testJavaConfigBean.getBatch();
}
}

测试读取配置

启动项目调用测试接口:

image-20200513115527824

apollo 控制台 增加修改并发布

image-20200513120010468

再次请求 spring boot 的测试接口

image-20200513120059188

发现配置已经更新了。

apollo 中的核心概念

在介绍高级特性前,我们有必要先来了解一下Apollo中的几个核心概念:

application (应用)

  • 这个很好理解,就是实际使用配置的应用,Apollo客户端在运行时需要知道当前应用是谁,从而可以去获取对应的配置
  • 每个应用都需要有唯一的身份标识 – appId,我们认为应用身份是跟着代码走的,所以需要在代码中配置,具体信息请参见Java客户端使用指南

environment (环境)

  • 配置对应的环境,Apollo客户端在运行时需要知道当前应用处于哪个环境,从而可以去获取应用的配置
  • 我们认为环境和代码无关,同一份代码部署在不同的环境就应该能够获取到不同环境的配置
  • 所以环境默认是通过读取机器上的配置(server.properties中的env属性)指定的,不过为了开发方便,我们也支持运行时通过System Property等指定,具体信息请参见Java客户端使用指南

cluster (集群)

  • 一个应用下不同实例的分组,比如典型的可以按照数据中心分,把上海机房的应用实例分为一个集群,把北京机房的应用实例分为另一个集群。
  • 对不同的cluster,同一个配置可以有不一样的值,如zookeeper地址。
  • 集群默认是通过读取机器上的配置(server.properties中的idc属性)指定的,不过也支持运行时通过System Property指定,具体信息请参见Java客户端使用指南

namespace (命名空间)

  • 一个应用下不同配置的分组,可以简单地把namespace类比为文件,不同类型的配置存放在不同的文件中,如数据库配置文件,RPC配置文件,应用自身的配置文件等
  • 应用可以直接读取到公共组件的配置namespace,如DAL,RPC等
  • 应用也可以通过继承公共组件的配置namespace来对公共组件的配置做调整,如DAL的初始数据库连接数

更多高级使用和配置请参考官方文档:

apollo 官方 Wiki