本文为Apollo配置中心使用篇学习笔记整理,主要参考资料如下:
如果对配置中心完全没有过了解的,可以先移步去了解一下常用的开源配置中心组件,如: SpringCloud Config和Nacos等。
本文为官方文档的一份精炼,如果查看完整细节,参考各个小节开头给出的官方文档链接
Spring Cloud Config: https://github.com/spring-cloud/spring-cloud-config
Apollo: https://github.com/ctripcorp/apollo
Nacos: https://github.com/alibaba/nacos
对比项目/配置中心 | spring cloud config | apollo | nacos(重点) |
---|---|---|---|
开源时间 | 2014.9 | 2016.5 | 2018.6 |
配置实时推送 | 弱支持(Spring Cloud Bus) | 支持(HTTP长轮询1s内) | 支持(HTTP长轮询1s内) |
版本管理 | 支持(Git) | 自动管理 | 自动管理 |
配置回滚 | 弱支持(Git+Bus) | 支持 | 支持 |
配置的灰度发布 | 理念上支持,可操作性不强 | 支持 | 1.1.0开始支持 |
权限管理 | 不支持(没有区分用户、角色、权限的概念) | 支持 | 1.2.0开始支持 |
多集群多环境 | 对集群概念支持较弱 | 支持 | 支持 |
多语言 | 只支持Java | Go,C++,Python,Java,.net,OpenAPI | Python,Java,Nodejs,OpenAPI |
分布式高可用最小集群数量 | Config-Server2+Git+MQ | Config2+Admin3+Portal*2+Mysql=8 | Nacos*3+MySql=4 |
配置格式校验 | 不支持 | 支持 | 支持 |
通信协议 | HTTP和AMQP | HTTP | HTTP |
数据一致性 | Git保证数据一致性,Config-Server从Git读取数据 | 数据库模拟消息队列,Apollo定时读消息 | HTTP异步通知 |
选择哪一个配置中心呢?
本节对应官方文档链接
Apollo(阿波罗)是一款可靠的分布式配置管理中心,诞生于携程框架研发部,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。
Apollo中有以下几个核心概念:
application (应用)
:当前使用apollo的集中配置管理的应用程序environment (环境)
:生产、测试、开发环境等。或者操作系统的环境:windows、linux等。cluster (集群)
:通常指部署到同一网络机房内的物理主机集群。集群配置信息存在的意义在于:项目部署在不同的集群,使用不同的配置,如:windows和linux服务器集群存在路径差异。如果项目部署在不同的集群,仍然可以使用相同的配置,则没有必要创建集群。namespace (命名空间)
:多个应用之间存在公共应用组件,为公共应用组件配置设置namespace(标签)。方便其他应用引用其配置。本节对应官方文档链接
本节对应官方文档链接
本节对应官方文档链接
Config Service
(基于Http long polling)
Admin Service
Meta Server
Eureka
Portal
Client
本节对应官方文档链接
在配置中心中,一个重要的功能就是配置发布后实时推送到客户端。下面我们简要看一下这块是怎么设计实现的。
用户通过Portal提供的界面发布配置后,配置发布请求最终交给Admin Service处理,Admin Service在配置发布后,需要通知所有的Config Service有配置发布,从而Config Service可以通知对应的客户端来拉取最新的配置。
从概念上来看,这是一个典型的消息使用场景,Admin Service作为producer发出消息,各个Config Service作为consumer消费消息。通过一个消息组件(Message Queue)就能很好的实现Admin Service和Config Service的解耦。
在实现上,考虑到Apollo的实际使用场景,以及为了尽可能减少外部依赖,我们没有采用外部的消息中间件,而是通过数据库实现了一个简单的消息队列。
实现方式如下:
AppId+Cluster+Namespace
AppId+Cluster+Namespace
后,会通知对应的客户端上一节中简要描述了NotificationControllerV2是如何得知有配置发布的,那NotificationControllerV2在得知有配置发布后是如何通知到客户端的呢?
实现方式如下:
上面过程涉及源码可以翻阅:RemoteConfigLongPollService ,客户端建立与服务端长链接源码简单来说如下所示:
本节对应官方文档链接
本节对应官方文档链接
Apollo除了支持API方式获取配置,也支持和Spring/Spring Boot集成,集成原理简述如下。
Spring从3.1版本开始增加了ConfigurableEnvironment和PropertySource
:
在运行时的结构形如:
需要注意的是,PropertySource之间是有优先级顺序的,如果有一个Key在多个property source中都存在,那么在前面的property source优先。
所以对上图的例子:
在理解了上述原理后,Apollo和Spring/Spring Boot集成的手段就呼之欲出了:在应用启动阶段,Apollo从远端获取配置,然后组装成PropertySource并插入到第一个即可,如下图所示:
相关代码可以参考: PropertySourcesProcessor
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
this.configUtil = ApolloInjector.getInstance(ConfigUtil.class);
//将ApolloPropertySource添加进Environment对象中,这样@Value或者@ConfigurationProperties进行属性注入时
//就可以从Environment环境上下文对象的PropertySource集合中发现ApolloPropertySource
//并从ApolloPropertySource中根据Key提取中我们想要的结果
initializePropertySources();
initializeAutoUpdatePropertiesFeature(beanFactory);
}
//注意: 以下方法极度简化,并进行了改动
private void initializePropertySources() {
CompositePropertySource composite=new CompositePropertySource(PropertySourcesConstants.APOLLO_PROPERTY_SOURCE_NAME);
//遍历所有命空间
for (String namespace : NAMESPACE_NAMES) {
//拿到命名空间下的配置
Config config = ConfigService.getConfig(namespace);
//组装成一个PropertySource加入CompositePropertySource中
composite.addPropertySource(configPropertySourceFactory.getConfigPropertySource(namespace, config));
}
//作为first优先级添加进environment中
environment.getPropertySources().addFirst(composite);
}
此部分涉及Spring Environment环境上下文模块的前置知识,如果不了解的小伙伴,可以先去了解一下环境上下文模块的架构设计和相关组件类及源码。
本节对应官方文档链接,本文未使用脚本安装,而是一步步安装,方便大家理解原理,如果需要使用脚本快速安装,可以参考给出的官方文档链接
Java版本最低要求
- Apollo服务端:1.8+
- Apollo客户端:1.7+
MySQL版本要求:5.6.5+
- Apollo的表结构对timestamp使用了多个default声明,所以需要5.6.5以上版本。
- mysql版本检查命令为: SHOW VARIABLES WHERE Variable_name = 'version';
注意:
- portal是apollo配置管理的WEB界面,一般部署在生产环境主机上
- config-service和admin-service是区分环境对配置进行管理的,因此通常生产环境部署一套,测试环境部署一套,研发环境部署一套
# 用管理员账号登录mysql之后执行命令,创建数据库、建表及插入示例数据。
mysql > source 你的SQL所在的linux文件路径/apolloportaldb.sql
# 建立test用户访问ApolloPortalDB和ApolloConfigDB
CREATE USER 'test'@'%' IDENTIFIED BY '你的密码';
GRANT ALL ON ApolloPortalDB.* TO 'test'@'%' IDENTIFIED BY '你的密码'; //只有执行了这一句才可以远程登陆
GRANT ALL ON ApolloConfigDB.* TO 'test'@'%' IDENTIFIED BY '你的密码';
#在当前目录下创建portal 目录,并将文件解压到里面
mkdir ./portal && unzip apollo-portal-2.1.0-github.zip -d ./portal
# DataSource
spring.datasource.url = jdbc:mysql://119.91.143.140:3306/ApolloPortalDB?characterEncoding=utf8
spring.datasource.username = test
spring.datasource.password = xxx
local.meta=http://localhost:8080
dev.meta=http://fill-in-dev-meta-server:8080
fat.meta=http://fill-in-fat-meta-server:8080
uat.meta=http://fill-in-uat-meta-server:8080
lpt.meta=${lpt_meta}
pro.meta=http://fill-in-pro-meta-server:8080
因为我们还没部署任何生产、测试、或者其他环境,所以暂时将文件内容删掉即可(上面的配置是文件内的默认配置,删掉)。
apollo默认支持的环境单词缩写解释:
启动Apollo配置中心:
执行启动脚本: ./startup.sh
访问测试: http://apollo-portal主机ip:9430/
输入用户名、密码 apollo/admin,登陆成功就表示我们安装成功了。
上一节我们成功安装了portal, portal是用来管理多个运行环境,比如:生产环境、测试环境、开发环境等。
本节我们就以DEV(开发环境)来为大家介绍apollo服务端其他组件的部署,也就是config-service和adminservice。
为了保证高可用,config service和admin service通常都会采用多实例集群部署
数据库导入: ConfigService 和 AdminServie都需要操作数据库ApolloConfigDB,sql文件下载链接上面已经给出
解压相关压缩文件
mkdir ./configservice && unzip apollo-configservice-2.1.0-github.zip -d ./configservice
mkdir ./adminservice && unzip apollo-configservice-2.1.0-github.zip -d ./adminservice
spring.datasource.url = jdbc:mysql://你的mysql所在主机ip:3306/ApolloConfigDB?characterEncoding=utf8
spring.datasource.username = test
spring.datasource.password = 你的用户密码
如果是集群部署可以参考下文对ConfigService和AdminService的配置修改,如果采用单机部署,可以直接跳到脚本启动部分,默认配置可以不改
假设ConfigService和AdminService都采用集群部署,并且部署在三个节点上,ConfigService端口号为9431,AdminService端口号为9432
# 在ApolloConfigDB中执行如下的SQL,配置eureka集群连接。
UPDATE apolloconfigdb.ServerConfig
SET ServerConfig.`Value`='http://192.168.161.3:9431/eureka/,http://192.168.161.4:9431/eureka/,http://192.168.161.5:9431/eureka/'
WHERE `Key`='eureka.service.url';
ConfigService和AdminService服务启动
执行启动脚本
/root/apollo/configservice/scripts/startup.sh; #先在每台机器上执行这个,因为包含eureka。
/root/apollo/adminservice/scripts/startup.sh; #然后每台机器上执行这个
eureka是spring cloud服务,所以该解决方案适用于所有的spring cloud服务。也就适用于configService和adminservice。在二者的application-github.properties文件中加入网卡选择配置。
spring.cloud.inetutils.preferredNetworks=192.168
spring.cloud.inetutils.ignoredInterfaces[0]=enp0s3
spring.cloud.inetutils.ignoredInterfaces[1]=docker0
eureka.instance.hostname=peer1
eureka.instance.instance-id: ${spring.application.name}-${eureka.instance.hostname}:${server.port}
将hostname改为peer1、peer2、peer3分别应用于三台主机,配置修改完成之后,重启configservice、adminservice
configService中默认包含了eureka,所以所有eureka遇到的问题都可以在configService应用中通过配置解决。
因为我们新增了DEV开发环境,并且部署了ConfigService和AdminService,所以需要将其告知Apollo Portal。方法就是修改portal应用的配置文件是config/apollo-env.properties。
dev.meta=http://192.168.161.3:9431,http://192.168.161.4:9431,http://192.168.161.5:9431
将dev.meta的配置指向configService服务。Config service地址也可以填入IP,0.11.0版本之前只支持填入一个IP。从0.11.0版本开始支持填入以逗号分隔的多个地址。如上配置所示。
不过对于生产环境还是建议使用域名,通过SLB(Software Load Balancer:nginx or haproxy)做动态负载均衡,因为机器扩容、缩容等都可能导致IP列表的变化。
因为我们修改了portal配置文件,所以portal也要重启。
/root/apollo/portal/scripts/startup.sh;
服务配置项统一存储在ApolloPortalDB.ServerConfig表中,可以通过管理员工具 - 系统参数
页面进行配置:
默认值是dev(开发环境),不用改。如果我们本节内容新增的是生产环境的配置,应该写上“dev,pro”,然后保存。查看管理员工具->系统信息,如下:
如果采用集群化部署,那么下面展示的就是多个实例,如第二张图所示
本节对应官方文档链接
Apollo默认定义了如下的一些权限:
Apollo的系统参数管理功能,就是给专业的IT运维人员用的,需要掌握JSON才能修改数据。并不针对小白用户提升用户体验。比如:我将样例部门二改为研发部,JSON代码如下:
[{"orgId":"TEST1","orgName":"样例部门1"},{"orgId":"yanfa","orgName":"研发部"}]
除非我们设置了系统参数role.create-application.enabled=true
,否则新建的用户默认就具有创建项目的permission了。如果设置了role.create-application.enabled=true
,需要通过:管理员工具->系统权限管理,为新建用户增加创建项目的权限。
官方文档参数说明链接
没有必要设置role.create-application.enabled=true,默认就可以,我们也没有必要进行下图中的设置。
创建项目成功后,会自动跳转到项目首页。
dhy作为项目负责人不可能所有的事都自己做,他安排配置管理员xpy负责项目的配置管理。那么就需要给dhy授权。点击右上角的“授权”按钮:
授权完成之后,zimud登录apollo之后就可以管理我们新建的项目apollo-javaclient-test了。
本节对应的官方文档链接
本节介绍一下普通的java项目如何集成apollo-java客户端进行集中配置管理。
点击“提交”按钮保存配置项目。然后点击绿色的“发布”按钮,将配置项信息发布。
注意:apollo-client最低要求的JDK版本为1.7,建议使用1.8+
<dependency>
<groupId>com.ctrip.framework.apollogroupId>
<artifactId>apollo-clientartifactId>
<version>1.7.0version>
dependency>
public class ApolloClientTest {
private static final String TEST_KEY="test.enabled";
@Test
public void testSimpleUse(){
Config config = ConfigService.getAppConfig();
//要获取的属性key,如果key不存在,使用我们提供的默认值
String val = config.getProperty(TEST_KEY, null);
System.out.println(TEST_KEY+": "+val);
}
}
-Dapp.id=javaclient-test -Denv=DEV -Ddev_meta=http://8.134.144.48:8080
如果获取配置失败,检查是否是因为config service和admin service在eureka注册中心注册的是内网IP,查看客户端日志输出即可,如果看到有私有IP地址出现,说明存在该问题,参考多网卡问题解决一节,或者我们可以手动指定注册的ip,如下所示:
eureka:
instance:
prefer-ip-address: true # 使用IP地址进行注册
ip-address: 192.168.1.100 # 指定要使用的IP地址
运行ApolloConfigTest,观察输出结果:“test.enabled: true”,表示我们从apollo配置中心获取配置成功了。
本节对应官方文档链接
<dependency>
<groupId>com.ctrip.framework.apollogroupId>
<artifactId>apollo-clientartifactId>
<version>1.7.0version>
dependency>
dev.meta=http://192.168.161.3:9431,http://192.168.161.4:9431,http://192.168.161.5:9431
#pro.meta=http://localhost:8081 //我们暂时没有在apollo中心添加生产环境,注释掉
app:
id: javaclient-test
apollo:
bootstrap:
enabled: true
meta: http://192.168.161.3:9431,http://192.168.161.4:9431,http://192.168.161.5:9431
@SpringBootApplication
@EnableApolloConfig
public class ApolloClientDemoMain {
public static void main(String[] args) {
SpringApplication.run(ApolloClientDemoMain.class,args);
}
}
apollo配置中心目前只支持properties格式,如果需要将使用yaml管理的配置放置到apollo上,我们需要转换一下:可以使用这个网址在线转换: ToYaml.com
-Denv=DEV
,也就是告诉springboot应用去加载DEV环境的配置信息。java -jar test.jar -Denv=DEV
集成了apollo客户端之后,以后所有的需要写入application.yml配置文件的配置信息,就不要再写到application.yml配置文件里面了,而是去apollo服务配置中心进行增加或者修改。
本节对应官方文档链接
Apollo客户端依赖于AppId,Apollo Meta Server等环境信息来工作,所以请确保下面的配置正确。每种配置都有好几种实现方式,我们在实际的开发中,只使用其中一种就可以,我会在我选择的那种上加上“推荐”二字:
Environment可以通过以下3种方式的任意一个配置:
目前,env支持以下几个值(大小写不敏感):
AppId是应用的身份信息,是配置中心的一个项目id,一般和应用名称保持一致,是从服务端获取配置的一个重要信息。有以下3种方式设置,按照优先级从高到底分别为:
-Dapp.id=YOUR-APP-ID
app.id=YOUR-APP-ID
app.id=YOUR-APP-ID
Apollo支持应用在不同的环境有不同的配置,所以需要在运行提供给Apollo客户端当前环境信息。默认情况下,meta server和config service是部署在同一个JVM进程,所以meta server的地址就是config service的地址。支持以下方式配置apollo meta server信息,按照优先级从高到底分别为:
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
Apollo客户端会把从服务端获取到的配置在本地文件系统缓存一份,用于在遇到服务不可用,或网络不通的时候,依然能从本地恢复配置,不影响应用正常运行。
本地缓存路径默认位于以下路径,所以请确保/opt/data或C:\opt\data\目录存在,且应用有读写权限。
本地配置文件会以下面的文件名格式放置于本地缓存路径下:{appId}+{cluster}+{namespace}.properties
Apollo 1.0.0版本开始支持以下方式自定义缓存路径,按照优先级从高到底分别为:
注:本地缓存路径也可用作于容灾目录,如果应用在所有config service都挂掉的情况下需要扩容,那么也可以先把配置从已有机器上的缓存路径复制到新机器上的相同缓存路径。
配置主要可以分为两类:
第一类配置的热更新也不是完全无法做到,可以自己写程序对配置数据变化进行监听,然后重新初始化其关联对象就可以实现。
如何实现配置热更新:
@RefreshScope //这里需要加上RefreshScope注解,结合ConfigurationProperties一起使用
@ConfigurationProperties(prefix = "user.init")
public class User{
private String password;
}
或者
public class Xxxxx{
@Value("${user.init.password}")
private String defaultPwd;
}
需要注意的是,@ConfigurationProperties
如果需要在Apollo配置变化时自动更新注入的值,需要配合使用EnvironmentChangeEvent或RefreshScope。相关代码实现,可以参考apollo-use-cases项目中的ZuulPropertiesRefresher.java和apollo-demo项目中的SampleRedisConfig.java以及SpringBootApolloRefreshConfig.java
本节对应官方文档链接
Apollo中的namespace理解为一个单独抽取出来的配置文件,利用namespace我们可以很方便的解决公共配置抽取与复用的问题。
为namespace名称自动添加部分前缀有利于保障namespace的全局唯一性。在那么space创建完成之后,我们发现项目的配置管理界面分为上下两部分:
app:
id: javaclient-test
apollo:
bootstrap:
enabled: true
namespace: application,TEST1.test-namespace
meta: http://xxx:8080
server:
port: 9200
@EnableApolloConfig({"application","TEST1.test-namespace"})
集群的概念要比namespace简单的多,“集群”就起到一个为应用按部署集群(机房)不同进行配置管理分类的作用
。某些大型企业,为了满足异地容灾的需要,通常将应用部署在不同的机房。项目A在B机房有一套配置(IP等环境不同),在C机房有一套配置。为了能区分配置的不同,apollo衍生出了集群的概念。
所以:apollo配置中心要为项目增加集群,一定是项目在不同集群(机房)部署的时候配置不同。如果应用在不同的集群(机房)可以使用相同的配置,就没必要为项目添加集群
。
apollo:
cluster: TEST
java -jar -Dapollo.cluster=TEST
灰度发布就是让配置先在部分实例生效,如果效果理想全量发布到所有实例,如果效果不理想就可以放弃当前的“灰度发布配置”。
Apollo与灰度发布:
这里以日志输出级别的动态调整为例,来演示一下灰度发布的使用:
@Service
public class LoggerConfiguration {
private static final Logger logger = LoggerFactory.getLogger(LoggerConfiguration.class);
private static final String LOGGER_TAG = "logging.level.";
@Resource
private LoggingSystem loggingSystem;
@ApolloConfig
private Config config;
@ApolloConfigChangeListener
private void configChangeListter(ConfigChangeEvent changeEvent) {
refreshLoggingLevels();
}
@PostConstruct
private void refreshLoggingLevels() {
Set<String> keyNames = config.getPropertyNames();
for (String key : keyNames) {
if (containsIgnoreCase(key, LOGGER_TAG)) {
String strLevel = config.getProperty(key, "info");
LogLevel level = LogLevel.valueOf(strLevel.toUpperCase());
loggingSystem.setLogLevel(key.replace(LOGGER_TAG, ""), level);
logger.info("{}:{}", key, strLevel);
}
}
}
private static boolean containsIgnoreCase(String str, String searchStr) {
if (str == null || searchStr == null) {
return false;
}
int len = searchStr.length();
int max = str.length() - len;
for (int i = 0; i <= max; i++) {
if (str.regionMatches(true, i, searchStr, 0, len)) {
return true;
}
}
return false;
}
}
但是在192.168.161.4的主机看不到上面的INFO级别的日志输出,因为我们通过设置灰度规则,指定了将192.168.161.4主机上的日志输出级别改为warn。warn的级别比INFO更高,所以在192.168.161.4看不到INFO级别的日志输出。
如果我们在通过灰度发布的配置测试下来比较理想,符合预期,那么就可以操作全量发布。
全量发布的效果是:
灰度版本的配置会合并回主版本
主版本的配置会自动进行一次发布
在全量发布页面,可以选择是否保留当前灰度版本,默认为不保留。
如果我们通过灰度发布的配置测试下来不理想或者不需要了,可以点击放弃灰度
正常情况下,我们获取Apollo配置的java客户端代码如下:
Config config = ConfigService.getAppConfig();
Integer defaultRequestTimeout = 200;
Integer requestTimeout = config.getIntProperty("requestTimeout", defaultRequestTimeout);
在某些场景下,应用需要在配置变化时获得通知,比如数据库连接的切换等,所以Apollo提供了监听配置变化的功能,Java示例如下:
//指定获取哪个命名空间下的配置
Config config = ConfigService.getConfig("FX.Hermes.Producer");
config.addChangeListener(new ConfigChangeListener() {
@Override
public void onChange(ConfigChangeEvent changeEvent) {
System.out.println("Changes for namespace " + changeEvent.getNamespace());
for (String key : changeEvent.changedKeys()) {
ConfigChange change = changeEvent.getChange(key);
System.out.println(String.format(
"Found change - key: %s, oldValue: %s, newValue: %s, changeType: %s",
change.getPropertyName(), change.getOldValue(),
change.getNewValue(), change.getChangeType()));
}
}
});
apollo-client 1.3.0版本开始对yaml/yml做了更好的支持,使用起来和properties格式一致。
Config config = ConfigService.getConfig("application.yml");
String someKey = "someKeyFromYmlNamespace";
String someDefaultValue = "someDefaultValueForTheKey";
String value = config.getProperty(someKey, someDefaultValue);
非yaml/yml格式的namespace: 获取时需要使用ConfigService.getConfigFile接口并指定Format,如ConfigFileFormat.XML。
String someNamespace = "test";
ConfigFile configFile = ConfigService.getConfigFile("test", ConfigFileFormat.XML);
String content = configFile.getContent();
//这个是最复杂的配置形式,指示Apollo注入FX.apollo和application.yml namespace的配置到Spring环境中,并且顺序在application前面
@Configuration
@EnableApolloConfig(order = 2)
public class SomeAppConfig {
@Bean
public TestJavaConfigBean javaConfigBean() {
return new TestJavaConfigBean();
}
}
@Configuration
@EnableApolloConfig(value = {"FX.apollo", "application.yml"}, order = 1)
public class AnotherAppConfig {}
Spring Boot除了支持上述两种集成方式以外,还支持通过application.properties/bootstrap.propertie
s来配置,该方式能使配置在更早的阶段注入
,比如使用@ConditionalOnProperty的场景或者是有一些spring-boot-starter在启动阶段就需要读取配置做一些事情(如dubbo-spring-boot-project),所以对于Spring Boot环境建议通过以下方式来接入Apollo(需要0.10.0及以上版本)。
# will inject 'application' namespace in bootstrap phase
apollo.bootstrap.enabled = true
apollo.bootstrap.enabled = true
# will inject 'application', 'FX.apollo' and 'application.yml' namespaces in bootstrap phase
apollo.bootstrap.namespaces = application,FX.apollo,application.yml
# will inject 'application' namespace in bootstrap phase
apollo.bootstrap.enabled = true
# put apollo initialization before logging system initialization
apollo.bootstrap.eagerLoad.enabled=true
Spring应用通常会使用Placeholder来注入配置,使用的格式形如 s o m e K e y : s o m e D e f a u l t V a l u e ,如 {someKey:someDefaultValue},如 someKey:someDefaultValue,如{timeout:100}。冒号前面的是key,冒号后面的是默认值。
建议在实际使用时尽量给出默认值,以免由于key没有定义导致运行时错误。
从v0.10.0开始的版本支持placeholder在运行时自动更新,具体参见PR #972。
如果需要关闭placeholder在运行时自动更新功能,可以通过以下两种方式关闭:
通过设置System Property apollo.autoUpdateInjectedSpringProperties,如启动时传入-Dapollo.autoUpdateInjectedSpringProperties=false
通过设置META-INF/app.properties中的apollo.autoUpdateInjectedSpringProperties属性,如
app.id=SampleApp
apollo.autoUpdateInjectedSpringProperties=false
Apollo同时还增加了几个新的Annotation来简化在Spring环境中的使用。
使用样例如下:
public class TestApolloAnnotationBean {
@ApolloConfig
private Config config; //inject config for namespace application
@ApolloConfig("application")
private Config anotherConfig; //inject config for namespace application
@ApolloConfig("FX.apollo")
private Config yetAnotherConfig; //inject config for namespace FX.apollo
@ApolloConfig("application.yml")
private Config ymlConfig; //inject config for namespace application.yml
/**
* ApolloJsonValue annotated on fields example, the default value is specified as empty list - []
*
* jsonBeanProperty=[{"someString":"hello","someInt":100},{"someString":"world!","someInt":200}]
*/
@ApolloJsonValue("${jsonBeanProperty:[]}")
private List<JsonBean> anotherJsonBeans;
@Value("${batch:100}")
private int batch;
//config change listener for namespace application
@ApolloConfigChangeListener
private void someOnChange(ConfigChangeEvent changeEvent) {
//update injected value of batch if it is changed in Apollo
if (changeEvent.isChanged("batch")) {
batch = config.getIntProperty("batch", 100);
}
}
//config change listener for namespace application
@ApolloConfigChangeListener("application")
private void anotherOnChange(ConfigChangeEvent changeEvent) {
//do something
}
//config change listener for namespaces application, FX.apollo and application.yml
@ApolloConfigChangeListener({"application", "FX.apollo", "application.yml"})
private void yetAnotherOnChange(ConfigChangeEvent changeEvent) {
//do something
}
//example of getting config from Apollo directly
//this will always return the latest value of timeout
public int getTimeout() {
return config.getIntProperty("timeout", 200);
}
//example of getting config from injected value
//the program needs to update the injected value when batch is changed in Apollo using @ApolloConfigChangeListener shown above
public int getBatch() {
return this.batch;
}
private static class JsonBean{
private String someString;
private int someInt;
}
}
很多情况下,应用可能已经有不少配置了,比如Spring Boot的应用,就会有bootstrap.properties/yml, application.properties/yml等配置。
在应用接入Apollo之后,这些配置是可以非常方便的迁移到Apollo的,具体步骤如下:
server.port
必须确保本地文件已经删除该配置项限于篇幅,下面剩余的部分大家自行阅读官方文档即可,写的非常清楚,我这边也就不再CV了
本地开发模式
测试模式