Apollo入门
公司项目使用了Apollo配置中心,找了个入门视频学习一下。只是一些基本的操作,架构有待深入研究。内容包括:
- Apollo的工作流程
- Apollo的4个维度管理Key-Value格式的配置:application (应用)、environment (环境)、cluster (集群)、namespace (命名空间)
- SpringBoot 集成Apollo的使用方法
- 生产环境的部署、灰度发布
项目地址:https://github.com/ctripcorp/apollo
参考视频: B站黑马 轻松入门Apollo分布式配置中心
配套讲义:http://www.pbteach.com/post/java_distribut/apollo_yq_doc/
1. 配置和配置中心
配置主要有以下几个特点:
- 配置是独立于程序的只读变量:独立于程序的,对于程序是只读的
- 配置伴随应用的整个生命周期:启动、运行
- 配置可以有多种加载方式:程序内部硬编码,配置文件,环境变量,启动参数,基于数据库等
- 配置需要治理:权限控制、不同环境和集群配置管理
微服务化的过程中,当系统从一个单体应用被拆分成分布式系统上一个个服务节点后,配置文件也必须跟着分割,这样配置就分散了。配置中心将配置从应用中剥离出来,统一管理,优雅的解决了配置的动态变更、持久化、运维成本等问题。应用自身既不需要去添加管理配置接口,也不需要自己去实现配置的持久化,更不需要引入“定时任务”以便降低运维成本。 即,配置中心就是一种统一管理各种应用配置的基础服务组件。
一个合格的配置中心需要满足一下几个特点:
- 配置项容易读取和修改
- 添加新配置简单直接
- 支持对配置的修改的检视以把控风险
- 可以查看配置修改的历史记录
- 不同部署环境支持隔离
2. Apollo入门
2.1 主流配置中心
- Disconf,百度
- Spring Cloud Config,Spring Cloud 生态组件,可以和Spring Cloud体系无缝整合。
- Apollo,携程
- Nacos,阿里
2.2 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的执行流程:
- 用户在配置中心对配置进行修改并发布
- Apollo配置中心会向客户端推送最新的配置
- Apollo客户端会定时从Apollo配置中心拉取最新的配置、更新本地配置并通知到应用
2.3 快速开始
Quick Start需要有bash环境,Windows用户安装Git Bash
01 环境要求
Java
- Apollo服务端:1.8+
- Apollo客户端:1.7+
MySQL:
- 版本要求:5.6.5+,Apollo的表结构对
timestamp
使用了多个default声明,所以需要5.6.5以上版本。
02 下载Quick Start安装包
下载地址:https://github.com/nobodyiam/apollo-build-scripts
- apollo-configservice
- apollo-adminservice
- apollo-porta
03 创建数据库
Apollo服务端共需要两个数据库:ApolloPortalDB
和ApolloConfigDB
,ApolloPortalDB只需要在生产环境部署一个即可,而ApolloConfigDB需要在每个环境部署一套。
ApolloPortalDB:
导入apolloportaldb.sql成功后,可以通过执行以下sql语句来验证:
select `Id`, `AppId`, `Name` from ApolloPortalDB.App;
Id | AppId | Name |
---|---|---|
1 | SampleApp | Sample App |
ApolloConfigDB:
导入apolloconfigdb.sql成功后,可以通过执行以下sql语句来验证:
select `NamespaceId`, `Key`, `Value`, `Comment` from ApolloConfigDB.Item;
NamespaceId | Key | Value | Comment |
---|---|---|---|
1 | timeout | 100 | sample timeout配置 |
04 配置数据库连接信息
编辑demo.sh,修改ApolloPortalDB和ApolloConfigDB相关的数据库连接信息。
# apollo config db info
apollo_config_db_url=jdbc:mysql://localhost:3306/ApolloConfigDB?characterEncoding=utf8
apollo_config_db_username=root
apollo_config_db_password=root
# apollo portal db info
apollo_portal_db_url=jdbc:mysql://localhost:3306/ApolloPortalDB?characterEncoding=utf8
apollo_portal_db_username=root
apollo_portal_db_password=root
05 启动
Apollo默认会启动3个服务,分别使用8070, 8080, 8090端口,确保这3个端口当前没有被使用。执行启动命令:
./demo.sh start
- apollo-configservice 8080
- apollo-adminservice 8090
- apollo-portal 8070
启动成功后,通过http://localhost:8070就可以访问,登录名/密码: apollo/admin
SampleApp进入配置界面,可以看到当前有一个配置timeout=100。
06 运行客户端程序
启动Demo客户端:
./demo.sh client
输入timeout
,就可以取到对应配置的值:
sh> timeout
> [SimpleApolloConfigDemo] Loading key : timeout with value: 100
2.4 核心概念
-
application (应用)
就是实际使用配置的应用,每个应用都需要有唯一的身份标识 – AppId,要使用相应的配置时,需要在代码中指定AppId
-
environment (环境)
配置对应的环境,比如生产环境、开发环境等。环境和代码无关,同一份代码部署在不同的环境就应该能够获取到不同环境的配置
-
cluster (集群)
一个应用下不同实例的分组,比如典型的可以按照数据中心分,把上海机房的应用实例分为一个集群,把北京机房的应用实例分为另一个集群。对不同的cluster,同一个配置可以有不一样的值,即进行值覆盖。
-
namespace (命名空间)
一个应用下不同配置的分组,可以简单地把namespace类比为文件,不同类型的配置存放在不同的文件中,如数据库配置文件等。分为public和private,public可以被其他应用关联,private只能被所属的应用获取到
3. Java客户端使用
3.1 发布配置
新建项目,指定唯一的身份标识 – AppId后,可以进行配置发布。支持的单个key-value形式输入,也可以直接使用文本模式批量添加、修改。
新增或者修改配置后,都需要点击发布才能生效。
3.2 获取配置
架构图:
Apollo支持应用在不同的环境有不同的配置,所以需要在运行提供给Apollo客户端当前环境的Apollo Meta Server信息。默认情况下,meta server和config service是部署在同一个JVM进程,所以meta server的地址就是config service的地址。
01 添加apollo客户端依赖
<dependency>
<groupId>com.ctrip.framework.apollo</groupId>
<artifactId>apollo-client</artifactId>
<version>1.1.0</version>
</dependency>
02 配置VM options
-Dapp.id: 指定应用的id
-Denv: 指定环境
-Ddev_meta: 指定当前环境的Apollo Meta Server信息,默认情况下所以meta server的地址就是config service的地址
-Dapp.id=apollo-quickstart -Denv=DEV -Dapollo_meta=http://localhost:8080
通过Java system property ${env}_meta
- 如果当前env是
dev
,那么用户可以配置-Ddev_meta=http://config-service-url
- 使用该配置方式,那么就必须要正确配置Environment
03 获取配置测试
devpublic class ApolloTest {
public static void main(String[] args) {
Config config = ConfigService.getAppConfig();
//获取配置信息,第一个参数:配置的key,第二个参数:默认值
String url = config.getProperty("url", null);
System.out.println(url);
}
}
ConfigService.getAppConfig()
:获取默认Namespace的配置对象,也可以指定Namespace的名称
config.getProperty()
:获取指定key的配置值
3. 3 SpringBoot集成方式
01 AppId
在Spring Boot application.properties或application.yml中配置
application.properties:
server.port=63000
#指定应用id
app.id=demo
#开启apollo.bootstrap,指定namespace
apollo.bootstrap.enabled=true
apollo.bootstrap.namespaces=application,datasource
02 Apollo Meta Server
Apollo支持应用在不同的环境有不同的配置,常用的指定方式有如下两种:
-
第一种:通过Java System Property的apollo.meta:
-Dapollo.meta=http://localhost:8080
-
第二种:在resources目录下新建apollo-env.properties文件
dev.meta=http://localhost:8080
03 本地缓存路径
Apollo客户端会把从服务端获取到的配置在本地文件系统缓存一份,用于在遇到服务不可用,或网络不通的时候,依然能从本地恢复配置,不影响应用正常运行。本地配置文件会以下面的文件名格式放置于配置的本地缓存路径下:{appId}+{cluster}+{namespace}.properties
可以通过Java System Property的apollo.cacheDir指定缓存路径,
-Dapollo.cacheDir=/opt/data/apollo-config
04 Environment
通过Java System Property的env来指定环境:-Denv=DEV
05 Cluster(集群)
通过Java System Property的apollo.cluste来指定集群:-Dapollo.cluster=DEFAULT
06 启用配置
在应用的启动类添加@EnableApolloConfig
注解即可:
@SpringBootApplication
@EnableApolloConfig
public class AccountApplication {
public static void main(String[] args) {
SpringApplication.run(AccountApplication.class, args);
}
}
测试:使用注解@Value("${jdbc.url}")
,通过key值即获取到对应的配置信息
@RestController
public class HelloController {
@GetMapping("/db-url")
public String getUrl(@Value("${jdbc.url}") String url) {
return url;
}
}
4. 灰度发布
- 对于一些对程序有比较大影响的配置,可以先在一个或者多个实例生效,观察一段时间没问题后再全量发布配置。
- 对于一些需要调优的配置参数,可以通过灰度发布功能来实现A/B测试。可以在不同的机器上应用不同的配置,不断调整、测评一段时间后找出较优的配置再全量发布配置。
通过创建灰度版本,可以对某些配置做灰度测试
灰度流程为:
- 创建灰度版本
- 配置灰度配置项
- 配置灰度规则。如果是私有的namespace可以按照客户端的IP进行灰度,如果是公共的namespace则可以同时按AppId和客户端的IP进行灰度
- 灰度发布
灰度版本最终有两种结果:全量发布和放弃灰度
全量发布:灰度的配置合到主版本并发布,所有的客户端都会使用合并后的配置
放弃灰度:删除灰度版本,所有的客户端都会使用回主版本的配置
注意事项:如果灰度版本已经有灰度发布过,那么修改灰度规则后,无需再次灰度发布就立即生效