Apollo配置中心.docx
《Apollo配置中心.docx》由会员分享,可在线阅读,更多相关《Apollo配置中心.docx(24页珍藏版)》请在冰豆网上搜索。
![Apollo配置中心.docx](https://file1.bdocx.com/fileroot1/2023-6/30/be0652ed-b642-408a-9d28-540abb2657dd/be0652ed-b642-408a-9d28-540abb2657dd1.gif)
Apollo配置中心
Apollo配置中心
资料来源:
更多资料请参考:
设计
一总体设计
1基础模型
2架构模块
3各模块概要介绍
1ConfigService
∙提供配置获取接口
∙提供配置更新推送接口(基于Httplongpolling)
o服务端使用实现异步化,从而大大增加长连接数量
o目前使用的tomcatembed默认配置是最多10000个连接(可以调整),使用了4C8G的虚拟机实测可以支撑10000个连接,所以满足需求(一个应用实例只会发起一个长连接)。
∙接口服务对象为Apollo客户端
2AdminService
∙提供配置管理接口
∙提供配置修改、发布等接口
∙接口服务对象为Portal
3MetaServer
∙Portal通过域名访问MetaServer获取AdminService服务列表(IP+Port)
∙Client通过域名访问MetaServer获取ConfigService服务列表(IP+Port)
∙MetaServer从Eureka获取ConfigService和AdminService的服务信息,相当于是一个EurekaClient
∙增设一个MetaServer的角色主要是为了封装服务发现的细节,对Portal和Client而言,永远通过一个Http接口获取AdminService和ConfigService的服务信息,而不需要关心背后实际的服务注册和发现组件
∙MetaServer只是一个逻辑角色,在部署时和ConfigService是在一个JVM进程中的
4Eureka
∙基于和提供服务注册和发现
∙ConfigService和AdminService会向Eureka注册服务,并保持心跳
∙为了简单起见,目前Eureka在部署时和ConfigService是在一个JVM进程中的(通过SpringCloudNetflix)
5Portal
∙提供Web界面供用户管理配置
∙通过MetaServer获取AdminService服务列表(IP+Port),通过IP+Port访问服务
∙在Portal侧做loadbalance、错误重试
6Client
∙Apollo提供的客户端程序,为应用提供配置获取、实时更新等功能
∙通过MetaServer获取ConfigService服务列表(IP+Port),通过IP+Port访问服务
∙在Client侧做loadbalance、错误重试
二、服务端设计
1配置发布后的实时推送设计
在配置中心中,一个重要的功能就是配置发布后实时推送到客户端。
下面我们简要看一下这块是怎么设计实现的。
上图简要描述了配置发布的大致过程:
1.用户在Portal操作配置发布
2.Portal调用AdminService的接口操作发布
3.AdminService发布配置后,发送ReleaseMessage给各个ConfigService
4.ConfigService收到ReleaseMessage后,通知对应的客户端
2发送ReleaseMessage的实现方式
AdminService在配置发布后,需要通知所有的ConfigService有配置发布,从而ConfigService可以通知对应的客户端来拉取最新的配置。
从概念上来看,这是一个典型的消息使用场景,AdminService作为producer发出消息,各个ConfigService作为consumer消费消息。
通过一个消息组件(MessageQueue)就能很好的实现AdminService和ConfigService的解耦。
在实现上,考虑到Apollo的实际使用场景,以及为了尽可能减少外部依赖,我们没有采用外部的消息中间件,而是通过数据库实现了一个简单的消息队列。
实现方式如下:
1.AdminService在配置发布后会往ReleaseMessage表插入一条消息记录,消息内容就是配置发布的AppId+Cluster+Namespace,参见
2.ConfigService有一个线程会每秒扫描一次ReleaseMessage表,看看是否有新的消息记录,参见
3.ConfigService如果发现有新的消息记录,那么就会通知到所有的消息监听器(),如,消息监听器的注册过程参见
4.NotificationControllerV2得到配置发布的AppId+Cluster+Namespace后,会通知对应的客户端
示意图如下:
ConfigService通知客户端的实现方式
上一节中简要描述了NotificationControllerV2是如何得知有配置发布的,那NotificationControllerV2在得知有配置发布后是如何通知到客户端的呢
实现方式如下:
1.客户端会发起一个Http请求到ConfigService的notifications/v2接口,也就是,参见
2.NotificationControllerV2不会立即返回结果,而是通过把请求挂起
3.如果在30秒内没有该客户端关心的配置发布,那么会返回Http状态码304给客户端
4.如果有该客户端关心的配置发布,NotificationControllerV2会调用DeferredResult的方法,传入有配置变化的namespace信息,同时该请求会立即返回。
客户端从返回的结果中获取到配置变化的namespace后,会立即请求ConfigService获取该namespace的最新配置。
三、客户端设计
上图简要描述了Apollo客户端的实现原理:
1.客户端和服务端保持了一个长连接,从而能第一时间获得配置更新的推送。
(通过HttpLongPolling实现)
2.客户端还会定时从Apollo配置中心服务端拉取应用的最新配置。
o这是一个fallback机制,为了防止推送机制失效导致配置不更新
o客户端定时拉取会上报本地版本,所以一般情况下,对于定时拉取的操作,服务端都会返回304-NotModified
o定时频率默认为每5分钟拉取一次,客户端也可以通过在运行时指定SystemProperty:
来覆盖,单位为分钟。
3.客户端从Apollo配置中心服务端获取到应用的最新配置后,会保存在内存中
4.客户端会把从服务端获取到的配置在本地文件系统缓存一份
o在遇到服务不可用,或网络不通的时候,依然能从本地恢复配置
5.应用程序可以从Apollo客户端获取最新的配置、订阅配置更新通知
Java客户端应用
一、准备工作
环境要求
∙Java:
+
∙Guava:
+
oApollo客户端默认会引用Guava19,如果你的项目引用了其它版本,请确保版本号大于等于
必选设置
Apollo客户端依赖于AppId,Environment等环境信息来工作
AppId
AppId是应用的身份信息,是从服务端获取配置的一个重要信息。
请确保classpath:
/META-INF/文件存在,并且其中内容形如:
=YOUR-APP-ID
文件位置参考如下:
也可通过SystemProperty传入信息,如
=YOUR-APP-ID
注:
是用来标识应用身份的唯一id,格式为string。
Environment
Apollo支持应用在不同的环境有不同的配置,所以Environment是另一个从服务器获取配置的重要信息。
Environment可以通过以下3种方式的任意一个配置:
1.通过JavaSystemProperty
o可以通过Java的SystemPropertyenv来指定环境
o在Java程序启动脚本中,可以指定-Denv=YOUR-ENVIRONMENT
▪如果是运行jar文件,需要注意格式是java-Denv=YOUR-ENVIRONMENT-jar
o注意key为全小写
2.通过操作系统的SystemEnvironment
o还可以通过操作系统的SystemEnvironmentENV来指定
o注意key为全大写
3.通过配置文件
o最后一个推荐的方式是通过配置文件来指定env=YOUR-ENVIRONMENT
o对于Mac/Linux,文件位置为/opt/settings/
o对于Windows,文件位置为C:
\opt\settings\
文件内容形如:
env=DEV
目前,env支持以下几个值(大小写不敏感)
∙DEV
∙FAT
∙UAT(目前不设UAT环境)
∙PRO
注:
运行时会通过env信息匹配metaserver信息,比如env是DEV的话,就会读取中中的dev_meta信息。
如果希望在运行时覆盖metaserver信息,有两个方法:
1.通过-D{env}_meta=xxx来覆盖,如-Ddev_meta=
2.准备一份单独的,放在程序运行的classpath中,或者放在程序运行目录下,具体可以参考的加载逻辑-和,需要注意的是在中需要用形如{env}.meta=xxx来覆盖,如=
本地缓存路径
Apollo客户端会把从服务端获取到的配置在本地文件系统缓存一份,用于在遇到服务不可用,或网络不通的时候,依然能从本地恢复配置,不影响应用正常运行。
本地缓存路径位于以下路径,所以请确保/opt/data或C:
\opt\data\目录存在,且应用有读写权限。
∙Mac/Linux:
/opt/data/{appId}/config-cache
∙Windows:
C:
\opt\data\{appId}\config-cache
本地配置文件会以下面的文件名格式放置于本地缓存路径下:
{appId}+{cluster}+{namespace}.properties
∙appId就是应用自己的appId,如
∙cluster就是应用使用的集群,一般在本地模式下没有做过配置的话,就是default
∙namespace就是应用使用的配置namespace,一般是application
文件内容以properties格式存储,比如如果有两个key,一个是,另一个是batch,那么文件内容就是如下格式:
=2000
batch=2000
注:
本地缓存路径也可用于容灾目录,如果应用在所有configservice都挂掉的情况下需要扩容,那么也可以先把配置从已有机器上的缓存路径复制到新机器上的相同缓存路径
可选设置
Cluster(集群)
Apollo支持配置按照集群划分,也就是说对于一个appId和一个环境,对不同的集群可以有不同的配置。
如果需要使用这个功能,你可以通过以下方式来指定运行时的集群:
1.通过JavaSystemProperty
o我们可以通过Java的SystemProperty设置来指定运行时集群(注意key为全小写)
o例如,可以在程序启动时通过=SomeCluster来指定运行时的集群为SomeCluster
2.通过配置文件
o首先确保/opt/settings/(Mac/Linux)或C:
\opt\settings\(Windows)在目标机器上存在
o在这个文件中,可以设置数据中心集群,如idc=xxx
o注意key为全小写
ClusterPrecedence(集群顺序)
1.如果和idc同时指定:
o我们会首先尝试从指定的集群加载配置
o如果没找到任何配置,会尝试从idc指定的集群加载配置
o如果还是没找到,会从默认的集群(default)加载
2.如果只指定了:
o我们会首先尝试从指定的集群加载配置
o如果没找到,会从默认的集群(default)加载
3.如果只指定了idc:
o我们会首先尝试从idc指定的集群加载配置
o如果没找到,会从默认的集群(default)加载
4.如果和idc都没有指定:
o我们会从默认的集群(default)加载配置
二、MavenDependency
由于客户端jar包中会包含metaserver信息,无法上传一个统一的jar包到中央仓库,所以请按照的文档说明打包并上传到自己公司的Maven私服。
应用在实际使用时只需要按照如下方式引入即可。
apollo-client
三、客户端用法
Apollo支持API方式和Spring整合方式,该怎么选择用哪一种方式
∙API方式灵活,功能完备,配置值实时更新(热发布),支持所有Java环境。
∙Spring方式接入简单,结合Spring有N种酷炫的玩法,如
oPlaceholder方式:
▪代码中使用,如:
@Value("${someKeyFromApollo:
someDefaultValue}")
▪中使用,如:
oSpringboot的方式
o缺点是这类注入的值在变化后不会重新注入,需要重启才会更新,如果需要配置值实时更新,可以参考后续的说明
∙Spring方式也可以结合API方式使用,如注入Apollo的Config对象,就可以照常通过API方式获取配置了:
∙@ApolloConfig
privateConfigconfig;入默认namespace的配置到Spring中
xmlns:
xsi=""
xmlns:
apollo=""
xsi:
schemaLocation="
">
--这个是最简单的配置形式,一般应用用这种形式就可以了,用来指示Apollo注入applicationnamespace的配置到Spring环境中-->
config/>
100}"/>
200}"/>
2.注入多个namespace的配置到Spring中
xmlns:
xsi=""
xmlns:
apollo=""
xsi:
schemaLocation="
">
--这个是最简单的配置形式,一般应用用这种形式就可以了,用来指示Apollo注入applicationnamespace的配置到Spring环境中-->
config/>
--这个是稍微复杂一些的配置形式,指示Apollo注入和namespace的配置到Spring环境中-->
confignamespaces=","/>
100}"/>
200}"/>
3.注入多个namespace,并且指定顺序
Spring的配置是有顺序的,如果多个propertysource都有同一个key,那么最终是顺序在前的配置生效。
apollo:
config如果不指定order,那么默认是最低优先级。
xmlns:
xsi=""
xmlns:
apollo=""
xsi:
schemaLocation="
">
configorder="2"/>
--这个是最复杂的配置形式,指示Apollo注入和namespace的配置到Spring环境中,并且顺序在application前面-->
confignamespaces=","order="1"/>
100}"/>
200}"/>
基于Java的配置(推荐)
相对于基于XML的配置,基于Java的配置是目前比较流行的方式,也是SpringBoot的默认配置方式。
注意@EnableApolloConfig要和@Configuration一起使用,不然不会生效。
1.注入默认namespace的配置到Spring中
入多个namespace的配置到Spring中
@Configuration
@EnableApolloConfig
publicclassSomeAppConfig{
@Bean
publicTestJavaConfigBeanjavaConfigBean(){
returnnewTestJavaConfigBean();
}
}
入多个namespace,并且指定顺序
roperties
∙appId就是应用自己的appId,如
∙cluster就是应用使用的集群,一般在本地模式下没有做过配置的话,就是default
∙namespace就是应用使用的配置namespace,一般是application
文件内容以properties格式存储,比如如果有两个key,一个是,另一个是batch,那么文件内容就是如下格式:
=2000
batch=2000
修改配置
在本地开发模式下,Apollo不会实时监测文件内容是否有变化,所以如果修改了配置,需要重启应用生效。
分布式部署
一、准备工作
Java
∙Apollo服务端:
+
∙Apollo客户端:
+
MySQL
∙版本要求:
连接上MySQL后,可以通过如下命令检查:
SHOWVARIABLESWHEREVariable_name='version';
Variable_name
Value
version
环境
分布式部署需要事先确定部署的环境以及部署方式。
Apollo目前支持以下环境:
∙DEV
o开发环境
∙FAT
o测试环境,相当于alpha环境(功能测试)
∙UAT
o集成环境,相当于beta环境(回归测试)
∙PRO
o生产环境
以ctrip为例,我们的部署策略如下:
∙Portal部署在生产环境的机房,通过它来直接管理FAT、UAT、PRO等环境的配置
∙MetaServer、ConfigService和AdminService在每个环境都单独部署,使用独立的数据库
∙MetaServer、ConfigService和AdminService在生产环境部署在两个机房,实现双活
∙MetaServer和ConfigService部署在同一个JVM进程内,AdminService部署在同一台服务器的另一个JVM进程内
我们的部署策略
网络策略
分布式部署的时候,apollo-configservice和apollo-adminservice需要把自己的IP和端口注册到MetaServer(apollo-configservice本身)。
Apollo客户端和Portal会从MetaServer获取服务的地址(IP+端口),然后通过服务地址直接访问。
所以如果实际部署的机器有多块网卡(如docker),或者存在某些网卡的IP是Apollo客户端和Portal无法访问的(如网络安全限制),那么我们就需要在apollo-configservice和apollo-adminservice中做相关限制以避免Eureka将这些网卡的IP注册到MetaServer。
具体文档可以参考章节。
具体而言,就是分别编辑和,然后把需要忽略的网卡加进去。
如下面这个例子就是对于apollo-configservice,把docker0和veth.*的网卡在注册到Eureka时忽略掉。
spring:
application:
name:
apollo-configservice
profiles:
active:
${apollo_profile}
cloud:
inetutils:
ignoredInterfaces:
-docker0
-veth.*
另外一种方式是直接指定要注册的IP,可以修改apollo-adminservice或apollo-configservice的文件,加入以下配置
eureka:
instance:
ip-address:
${指定的IP}
最后一种方式是直接指定要注册的IP+PORT,可以修改apollo-adminservice或apollo-configservice的文件,加入以下配置
eureka:
instance:
homePageUrl:
preferIpAddress:
false
二、部署步骤
创建数据库
Apollo服务端共需要两个数据库:
ApolloPortalDB和ApolloConfigDB,我们把数据库、表的创建和样例数据都分别准备了sql文件,只需要导入数据库即可。
注意:
如果你本地已经创建过Apollo数据库,请注意备份数据。
我们准备的sql文件会清空Apollo相关的表。
创建ApolloPortalDB
通过各种MySQL客户端导入即可。
下面以MySQL原生客户端为例:
source/your_local_path/sql/
导入成功后,可以通过执行以下sql语句来验证:
select`Id`,`Key`,`Value`,`Comment`from`ApolloPortalDB`.`ServerConfig`limit1;
Id
Key
Value
Comment
1
dev
可支持的环境列表
注:
ApolloPortalDB只需要在生产环境部署一个即可
创建ApolloConfigDB
通过各种MySQL客户端导入即可。
下面以MySQL原生客户端为例:
source/your_local_path/sql/
导入成功后,可以通过执行以下sql语句来验证:
select`Id`,`Key`,`Value`,`Comment`from`ApolloConfigDB`.`ServerConfig`limit1;
Id
Key
Value
Comment
1
Eureka服务Url
注:
ApolloCo