本文主要是介绍Apollo配置中心最佳实践,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
携程配置中心地址:GitCode - 全球开发者的开源社区,开源代码托管平台
1.1 Apollo配置中心介绍
Apollo(阿波罗)是开源配置管理中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性。
主要特性:
Apollo | |
功能特性 | |
静态配置管理 | 支持 |
动态配置管理 | 支持 |
统一管理 | 支持 |
多维度管理 | 支持(应用、环境、集群、命名空间) |
本地配置缓存 | 支持 |
配置生效时间 | 实时 |
配置更新推送 | 支持 |
配置定时拉去 | 支持 |
用户权限管理 | 支持 |
授权、审核、审计 | 支持 |
配置版本管理 | 支持 |
配置合规检测 | 支持 |
实例配置监控 | 支持 |
灰度发布 | 支持 |
告警通知 | 支持,邮件方式告警 |
OpenAPI | 支持 |
技术路线 | |
支持SpringBoot | 支持 |
支持SpringCloud | 支持 |
客户端支持 | Java、.Net |
业务系统侵入性 | 侵入性弱 |
依赖组件 | Eureka |
可用性 | |
单点故障(SPOF) | 支持HA部署 |
多数据中心部署 | 支持 |
配置获取性能 | 官方说比spring快 |
易用性 | |
配置界面 | 统一界面(一个界面多个服务) |
社区活跃度 | 非常高 |
1.1.1 核心概念
1.1.1.1 application (应用)
实际使用配置的应用,需要有唯一的身份标识 -- appId
从而可以去获取对应的配置。
1.1.1.2 environment环境
配置对应的环境,Apollo客户端在运行时需要知道当前应用处于哪个环境,从而可以去获取应用的配置
我们认为环境和代码无关,同一份代码部署在不同的环境就应该能够获取到不同环境的配置
1.1.1.3 cluster (集群)
一个应用下不同实例的分组,比如典型的可以按照数据中心分,把上海机房的应用实例分为一个集群,把北京机房的应用实例分为另一个集群。
对不同的cluster,同一个配置可以有不一样的值,如dubbo地址。
1.1.1.4 namespace (命名空间)
一个应用下不同配置的分组,可以简单地把namespace类比为
文件,不同类型的配置存放在不同的文件中,如数据库配置文件,RPC配置文件,应用自身的配置文件等
例如:
应用里面redis配置地址
Apollo namespace对应为:
1.1.2 整体架构
简易模型
1.1.2.1 四个核心模块及其主要功能
1. ConfigService
- 提供配置获取接口
- 提供配置推送接口
- 服务于Apollo客户端
2. AdminService
- 提供配置管理接口
- 提供配置修改发布接口
- 服务于管理界面Portal
3. Client
- 为应用获取配置,支持实时更新
- 通过MetaServer获取ConfigService的服务列表
- 使用客户端软负载SLB方式调用ConfigService
4. Portal
- 配置管理界面
- 通过MetaServer获取AdminService的服务列表
- 使用客户端软负载SLB方式调用AdminService
1.1.2.2 客户端设计
1.2 NameSpace数据结构
1.2.1 权限
说明:针对应用对应的客户端来说
- 私有权限private只能被所属的应用获取到。
- 公有权限public能被任何应用获取。
1.2.2 类型
- 私有类型的Namespace具有private权限。
- 公共类型的Namespace具有public权限,所以公共的Namespace的名称必须全局唯一。
- 关联类型又可称为继承类型,关联类型具有private权限。
关联类型的Namespace继承于公共类型的Namespace,
用于覆盖公共Namespace的某些配置。
1.3 权限说明
1.3.1 用户权限
1.3.2 使用场景
以广告系统为例
Apollo配置中心地址:GitCode - 全球开发者的开源社区,开源代码托管平台
1.4 客户端加载机制
1.4.1 与Springboot集成
Apollo和Spring/SpringBoot集成的手段:在应用启动阶段,Apollo从远端获取配置,然后组装成PropertySource并插入到第一个即可,如下图所示:
1.4.2 公共组件配置的获取规则
加载顺序
1. 首先查找运行时cluster的配置(通过apollo.cluster指定)
2. 如果没有找到,则查找数据中心cluster的配置
3. 如果还是没有找到,则返回默认cluster的配置
所以如果应用部署在A数据中心,但是用户没有在Apollo创建cluster,那么获取的配置就是默认cluster(default)的。
如果应用部署在A数据中心,同时在运行时指定了SomeCluster,但是没有在Apollo创建cluster,那么获取的配置就是A数据中心cluster的配置,如果A数据中心cluster没有配置的话,那么获取的配置就是默认cluster(default)的。
以FX.Hermes.Producer
为例,hermes producer是hermes发布的公共组件。当使用下面的语句获取配置时,我们称之为获取公共组件的配置。
Config config = ConfigService.getConfig("FX.Hermes.Producer");
对这种情况的配置获取规则,简而言之如下:
1. 首先获取当前应用下的FX.Hermes.Producer
namespace的配置
2. 然后获取hermes应用下FX.Hermes.Producer
namespace的配置
3. 上面两部分配置的并集就是最终使用的配置,如有key一样的部分,以当前应用优先
1.4.3 广告系统使用
1.4.3.1 统一引入客户端
优势:
1、统一管理版本。
2、便于SPI扩展。
1.4.3.2 必选设置
appId、Meta Server、本地缓存路径
appId
- System Property
通过System Property传入app.id信息,如
-Dapp.id= iss-advert001
- Spring Boot application.properties
通过Spring Boot的application.properties文件配置,如
app.id= iss-advert001
- app.properties
确保classpath:/META-INF/app.properties文件存在,并且其中内容形如:
app.id= iss-advert001
Apollo Meta Server
- 在Java程序启动脚本中,可以指定
-Dapollo.meta=http://config-service-url
- 通过Spring Boot的配置文件
可以在Spring Boot的application.properties
中指定 apollo.meta=http://config-service-url
- 通过操作系统的环境变量指定
APOLLO_META
- 通过
server.properties
配置文件
- 可以在
server.properties
配置文件中指定apollo.meta=http://config-service-url
- 对于Mac/Linux,文件位置为
/opt/settings/server.properties
- 对于Windows,文件位置为
C:\opt\settings\server.properties
- 通过
app.properties
配置文件
可以在classpath:/META-INF/app.properties
指定apollo.meta=http://config-service-url
- 通过Java system property
${env}_meta
如果当前env是dev
,那么用户可以配置-Ddev_meta=http://config-service-url
如果通过以上各种手段都无法获取到Meta Server地址,Apollo最终会fallback到http://apollo.meta
作为Meta Server地址
本地缓存路径
默认
- Mac/Linux: /opt/data/{appId}/config-cache
- Windows: C:\opt\data\{appId}\config-cache
- 通过Java启动参数 -Dapollo.cacheDir= /mnt/iss/web/
- 通过Spring Boot的配置文件
可以在Spring Boot的application.properties
或bootstrap.properties
中指定apollo.cacheDir=
/mnt/iss/web/
- 通过操作系统的环境变量
APOLLO_CACHEDIR
- 通过
server.properties
配置文件
1.4.3.3 可选设置
Environment
1. 通过Java System Property
可以通过Java的System Property env来指定环境
在Java程序启动脚本中,可以指定-Denv=YOUR-ENVIRONMENT
如果是运行jar文件,需要注意格式是java -Denv=YOUR-ENVIRONMENT -jar xxx.jar
注意key为全小写
2. 通过操作系统的System Environment
还可以通过操作系统的System Environment ENV来指定
注意key为全大写
通过配置文件
3. 最后一个推荐的方式是通过配置文件来指定env=YOUR-ENVIRONMENT
对于Mac/Linux,文件位置为/opt/settings/server.properties
对于Windows,文件位置为C:\opt\settings\server.properties
文件内容形如:
env=DEV
Cluster(集群)
通过Java System Property apollo.cluster
在Java程序启动脚本中,可以指定-Dapollo.cluster=SomeCluster
- 通过Spring Boot的配置文件
可以在Spring Boot的application.properties
或bootstrap.properties
中指定apollo.cluster=SomeCluster
2. 通过server.properties配置文件
3. 可以在server.properties配置文件中指定idc=xxx
对于Mac/Linux,文件位置为/opt/settings/server.properties
对于Windows,文件位置为C:\opt\settings\server.properties
综上:
Springboot application.properties
:指定
app.id=iss-advert001
#配置中心缓存文件目录,配置于此,便于开发人员调试更改本地路径
apollo.cacheDir=../jar包上一层目录 /mnt/iss/web
/mnt/iss/boot/应用名/cache ../webapp/
方案一:选用
在Java程序启动脚本中,指定
-Denv=YOUR-ENVIRONMENT
-Dapollo.cluster=SomeCluster
-Dapollo.meta=http://config-service-url
此方案涉及多个环境,需要配置对应的启动脚本。
方案二:
通过server.properties
配置文件
对于Mac/Linux,文件位置为/opt/settings/server.properties
env=DEV
idc=SomeCluster
apollo.meta=http://config-service-url
机器上配置对应的集群名字和注册中心地址
应用对应的缓存目录部署应用时不用删除。
1.4.3.4 客户端使用
- 直接以API方式使用:
- 基于XML的配置
@ApolloConfig
private Config config; //inject config for namespace application
1.注入默认namespace的配置到Spring中
http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd
<!-- 这个是最简单的配置形式,一般应用用这种形式就可以了,用来指示Apollo注入application namespace的配置到Spring环境中 -->
<apollo:config/>
<!-- 这个是稍微复杂一些的配置形式,指示Apollo注入FX.apollo和FX.soa namespace的配置到Spring环境中 -->
<apollo:config namespaces="FX.apollo,FX.soa"/>
- 基于Java的配置(推荐)
注意@EnableApolloConfig
要和@Configuration
一起使用,不然不会生效。
客户端应用ID
建议项目名称
1.5 部署架构方案
1.6 服务端客户端通信
1.6.1.1 实时生效(1s)
- 用户在 Portal 操作配置发布
- Portal 调用 Admin Service 的接口操作发布
- Admin Service 发布配置后,发送 ReleaseMessage 给各个Config Service
- Config Service 收到 ReleaseMessage 后,通知对应的客户端
portal发布配置流程:1、2步
3、4步
Admin Service在配置发布后,需要通知所有的 Config Service有配置发布,从而 Config Service 可以通知对应的客户端来拉取最新的配置。
具体实现
- RemoteConfigRepository ,定时轮询 Config Service 的配置读取 /configs/{appId}/{clusterName}/{namespace:.+} 接口。
- RemoteConfigLongPollService ,长轮询 Config Service 的配置变更通知 /notifications/v2 接口。
- 当有新的通知时,触发 RemoteConfigRepository ,立即轮询 Config Service 的配置读取 /configs/{appId}/{clusterName}/{namespace:.+} 接口。
² 一个 Namespace 对应一个 RemoteConfigRepository 。
² 多个 RemoteConfigRepository ,注册到全局唯一的 RemoteConfigLongPollService 中。
为什么不在 long polling 的返回结果中直接返回更新的结果呢?
保持逻辑的简单,目前的做法推送只负责做简单的通知,不需要去计算客户端的配置应该是什么,因为计算逻辑挺复杂的,需要考虑集群,关联,灰度等。
在满足幂等性,实时性的基础上保持设计的简单
推拉结合?
1、client 的定时轮询,可以保持最终一致。
2、client 的长轮询,是定时轮训的“实时”补充。
Apollo配置中心地址:GitCode - 全球开发者的开源社区,开源代码托管平台
这篇关于Apollo配置中心最佳实践的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!