https://blog.youkuaiyun.com/Dbh321/article/details
apollo官网源码:https://github.com/apolloconfig/apollo
apollo使用文档:https://www.apolloconfig.com/#/zh/README
https://www.apolloconfig.com/#/zh/README
配置的概念
按照我们的理解,配置有以下几个属性:
配置是独立于程序的只读变量
配置首先是独立于程序的,同一份程序在不同的配置下会有不同的行为。
其次,配置对于程序是只读的,程序通过读取配置来改变自己的行为,但是程序不应该去改变配置。
常见的配置有:DB Connection Str、Thread Pool Size、Buffer Size、Request Timeout、Feature Switch、Server Urls等。
配置伴随应用的整个生命周期
配置贯穿于应用的整个生命周期,应用在启动时通过读取配置来初始化,在运行时根据配置调整行为。
配置可以有多种加载方式
配置也有很多种加载方式,常见的有程序内部hard code,配置文件,环境变量,启动参数,基于数据库等
配置需要治理
权限控制
由于配置能改变程序的行为,不正确的配置甚至能引起灾难,所以对配置的修改必须有比较完善的权限控制
不同环境、集群配置管理
同一份程序在不同的环境(开发,测试,生产)、不同的集群(如不同的数据中心)经常需要有不同的配置,所以需要有完善的环境、集群配置管理
框架类组件配置管理
还有一类比较特殊的配置 - 框架类组件配置,比如CAT客户端的配置。
虽然这类框架类组件是由其他团队开发、维护,但是运行时是在业务实际应用内的,所以本质上可以认为框架类组件也是应用的一部分。
这类组件对应的配置也需要有比较完善的管理方式。
apollo基本概念
- application (应用)
这个很好理解,就是实际使用配置的应用,Apollo客户端在运行时需要知道当前应用是谁,从而可以去获取对应的配置
每个应用都需要有唯一的身份标识 – appId
例如aicall是一个应用 - environment (环境)
配置对应的环境,Apollo客户端在运行时需要知道当前应用处于哪个环境,从而可以去获取应用的配置
我们认为环境和代码无关,同一份代码部署在不同的环境就应该能够获取到不同环境的配置
所以环境默认是通过读取机器上的配置(server.properties中的env属性)指定的,不过为了开发方便,我们也支持运行时通过System Property等指定。
例如UAT,SIT,PRO - cluster (集群)
一个应用下不同实例的分组,比如典型的可以按照数据中心分,把上海机房的应用实例分为一个集群,把北京机房的应用实例分为另一个集群。
对不同的cluster,同一个配置可以有不一样的值,如zookeeper地址。
集群默认是通过读取机器上的配置(server.properties中的idc属性)指定的,不过也支持运行时通过System Property指定
目前aicall系统未做集群区分 - namespace (命名空间)
一个应用下不同配置的分组,可以简单地把namespace类比为文件,不同类型的配置存放在不同的文件中,如数据库配置文件,RPC配置文件,应用自身的配置文件等
应用可以直接读取到公共组件的配置namespace,如DAL,RPC等
应用也可以通过继承公共组件的配置namespace来对公共组件的配置做调整,如DAL的初始数据库连接数
可以为每个模块,做一个单独的namespace
模块概要
Config Service
提供配置获取接口
提供配置更新推送接口(基于Http long polling)
服务端使用Spring DeferredResult实现异步化,从而大大增加长连接数量
目前使用的tomcat embed默认配置是最多10000个连接(可以调整),使用了4C8G的虚拟机实测可以支撑10000个连接,所以满足需求(一个应用实例只会发起一个长连接)。
接口服务对象为Apollo客户端
Admin Service
提供配置管理接口
提供配置修改、发布等接口
接口服务对象为Portal
Meta Server
● Portal通过域名访问Meta Server获取Admin Service服务列表(IP+Port)
● Client通过域名访问Meta Server获取Config Service服务列表(IP+Port)
● Meta Server从Eureka获取Config Service和Admin Service的服务信息,相当于是一个Eureka Client
● 增设一个Meta Server的角色主要是为了封装服务发现的细节,对Portal和Client而言,永远通过一个Http接口获取Admin Service和Config Service的服务信息,而不需要关心背后实际的服务注册和发现组件
● Meta Server只是一个逻辑角色,在部署时和Config Service是在一个JVM进程中的,所以IP、端口和Config Service一致
Eureka
● 基于Eureka和Spring Cloud Netflix提供服务注册和发现
● Config Service和Admin Service会向Eureka注册服务,并保持心跳
● 为了简单起见,目前Eureka在部署时和Config Service是在一个JVM进程中的(通过Spring Cloud Netflix)
Portal
● 提供Web界面供用户管理配置
● 通过Meta Server获取Admin Service服务列表(IP+Port),通过IP+Port访问服务
● 在Portal侧做load balance、错误重试
Client
● Apollo提供的客户端程序,为应用提供配置获取、实时更新等功能
● 通过Meta Server获取Config Service服务列表(IP+Port),通过IP+Port访问服务
● 在Client侧做load balance、错误重试
功能实现
配置发布后的实时推送设计
在配置中心中,一个重要的功能就是配置发布后实时推送到客户端。

上图简要描述了配置发布的大致过程:
- 用户在Portal操作配置发布
- Portal调用Admin Service的接口操作发布
- Admin Service发布配置后,发送ReleaseMessage给各个Config Service
- Config Service收到ReleaseMessage后,通知对应的客户端
发送ReleaseMessage的实现方式
Admin Service在配置发布后,需要通知所有的Config Service有配置发布,从而Config Service可以通知对应的客户端来拉取最新的配置。
从概念上来看,这是一个典型的消息使用场景,Admin Service作为producer发出消息,各个Config Service作为consumer消费消息。通过一个消息组件(Message Queue)就能很好的实现Admin Service和Config Service的解耦。
在实现上,考虑到Apollo的实际使用场景,以及为了尽可能减少外部依赖,我们没有采用外部的消息中间件,而是通过数据库实现了一个简单的消息队列。
实现方式如下: - Admin Service在配置发布后会往ReleaseMessage表插入一条消息记录,消息内容就是配置发布的AppId+Cluster+Namespace
- Config Service有一个线程会每秒扫描一次ReleaseMessage表,看看是否有新的消息记录
- Config Service如果发现有新的消息记录,那么就会通知到所有的消息监听器(ReleaseMessageListener),如NotificationControllerV2
- NotificationControllerV2得到配置发布的AppId+Cluster+Namespace后,会通知对应的客户端
示意图如下:
Config Service通知客户端的实现方式
实现方式如下:
-
客户端会发起一个Http请求到Config Service的notifications/v2接口
-
NotificationControllerV2不会立即返回结果,而是通过Spring DeferredResult把请求挂起
-
如果在60秒内没有该客户端关心的配置发布,那么会返回Http状态码304给客户端
-
如果有该客户端关心的配置发布,NotificationControllerV2会调用DeferredResult的setResult方法,传入有配置变化的namespace信息,同时该请求会立即返回。客户端从返回的结果中获取到配置变化的namespace后,会立即请求Config Service获取该namespace的最新配置。
客户端实现 -
客户端和服务端保持了一个长连接,从而能第一时间获得配置更新的推送。(通过Http Long Polling实现)
-
客户端还会定时从Apollo配置中心服务端拉取应用的最新配置。
○ 这是一个fallback机制,为了防止推送机制失效导致配置不更新
○ 客户端定时拉取会上报本地版本,所以一般情况下,对于定时拉取的操作,服务端都会返回304 - Not Modified
○ 定时频率默认为每5分钟拉取一次,客户端也可以通过在运行时指定System Property: apollo.refreshInterval来覆盖,单位为分钟。 -
客户端从Apollo配置中心服务端获取到应用的最新配置后,会保存在内存中
-
客户端会把从服务端获取到的配置在本地文件系统缓存一份
○ 在遇到服务不可用,或网络不通的时候,依然能从本地恢复配置 -
应用程序可以从Apollo客户端获取最新的配置、订阅配置更新通知
接入参数配置
Apollo客户端依赖于AppId,Apollo Meta Server等环境信息来工作
AppId设置方式(优先级由低到高):
- System Property -Dapp.id=YOUR-APP-ID
- 操作系统的System Environment APP_ID=YOUR-APP-ID
- Spring Boot application.properties app.id=YOUR-APP-ID 该配置方式不适用于多个war包部署在同一个tomcat的使用场景
- app.properties app.id=YOUR-APP-ID
Apollo Meta Server设置方式(优先级由低到高): - 通过Java System Property apollo.meta
○ 可以通过Java的System Property apollo.meta来指定
○ 在Java程序启动脚本中,可以指定-Dapollo.meta=http://config-service-url
■ 如果是运行jar文件,需要注意格式是java -Dapollo.meta=http://config-service-url -jar xxx.jar
○ 也可以通过程序指定,如System.setProperty(“apollo.meta”, “http://config-service-url”); - 通过Spring Boot的配置文件
○ 可以在Spring Boot的application.properties或bootstrap.properties中指定apollo.meta=http://config-service-url该配置方式不适用于多个war包部署在同一个tomcat的使用场景 - 通过操作系统的System Environment APOLLO_META
○ 可以通过操作系统的System Environment APOLLO_META来指定
○ 注意key为全大写,且中间是_分隔 - 通过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
○ 使用该配置方式,那么就必须要正确配置Environment,详见1.2.4.1 Environment - 通过操作系统的System Environment ${ENV}_META (1.2.0版本开始支持)
○ 如果当前env是dev,那么用户可以配置操作系统的System Environment DEV_META=http://config-service-url
○ 注意key为全大写
○ 使用该配置方式,那么就必须要正确配置Environment - 通过apollo-env.properties文件
○ 用户也可以创建一个apollo-env.properties,放在程序的classpath下,或者放在spring boot应用的config目录下
○ 使用该配置方式,那么就必须要正确配置Environment
○ 文件内容形如:dev.meta=http://1.1.1.1:8080 fat.meta=http://apollo.fat.xxx.com uat.meta=http://apollo.uat.xxx.com pro.meta=http://apollo.xxx.com
Environment可以通过以下3种方式的任意一个配置: - 通过Java System Property
○ 可以通过Java的System Property env来指定环境
○ 在Java程序启动脚本中,可以指定-Denv=YOUR-ENVIRONMENT
■ 如果是运行jar文件,需要注意格式是java -Denv=YOUR-ENVIRONMENT -jar xxx.jar
○ 注意key为全小写 - 通过操作系统的System Environment
○ 还可以通过操作系统的System Environment ENV来指定
○ 注意key为全大写 - 通过配置文件
○ 最后一个推荐的方式是通过配置文件来指定env=YOUR-ENVIRONMENT
○ 对于Mac/Linux,默认文件位置为/opt/settings/server.properties
○ 对于Windows,默认文件位置为C:\opt\settings\server.properties
文件内容形如:env=DEV
目前,env支持以下几个值(大小写不敏感):
● DEV
○ Development environment
● FAT
○ Feature Acceptance Test environment
● UAT
○ User Acceptance Test environment
● PRO
○ Production environment
加密支持
支持jasypt-spring-boot自动实现加解密功能。
使用时将加密后的数据配置到applo中,添加配置时使用ENC()包含配置,如加密配置为xxx,则ENC(xxx)
在项目的配置文件中,增加加密密钥的配置,例如:
jasypt.encryptor.password = klklklklklklklkl
1288

被折叠的 条评论
为什么被折叠?



