公司最近使用了携程的开源框架apollo来对配置文件进行管理,总体上来说还是非常简单的。
1.接入apollo
1.1 在yml或者properties文件中添加apollo配置
在resource目录下创建bootstrap.properties/yml或者application.properties/yml,配置内容如下:
#apollo中的服务名称
app.id=你在apollo后台中的项目唯一标示码
#注入默认application
apollo.bootstrap.enabled=true
#优先加载apollo配置
apollo.bootstrap.eagerLoad.enabled=true
#注入多个namespace,配置在前的优先级更高
apollo.bootstrap.namespaces=profile,application
1.2将现有resource下的yml或者properties配置添加到apollo后台,并删除本地文件
1.3增加pom依赖
com.ctrip.framework.apollo
apollo-client
1.4.0
1.4如果代码中有使用 @ConfigurationProperties 。通过增加以下代码来支持自动更新,同时这段代码也支持了日志级别自动更新
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.cloud.context.scope.refresh.RefreshScope;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Slf4j
@Component
public class ApolloRefreshConfig {
@Resource
private AppConfig appConfig;
@Resource
private RefreshScope refreshScope;
@Resource
private ApplicationContext applicationContext;
//value对应配置的namespace
//prefixes 为你的配置前缀,没有可不写
//refreshScope.refresh的参数是自定义配置的BeanName
@ApolloConfigChangeListener(value = {"profile", "application"}, interestedKeyPrefixes = "prefixes.")
public void appConfigChange(ConfigChangeEvent changeEvent) {
log.info("配置更新前|{}", appConfig);
refreshScope.refresh("appConfig");
log.info("配置更新后|{}", appConfig);
}
@ApolloConfigChangeListener(value = {"profile", "application"}, interestedKeyPrefixes = "logging.level.")
public void loggingLevelChange(ConfigChangeEvent changeEvent) {
applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));
log.info("日志级别配置更新完成|{}", changeEvent.changedKeys());
}
}
1.5 如果项目中有使用xml配置的,例如dubbo的provider和consumer等配置中需要引用apollo中的配置项,则需在xml配置文件中添加如下配置,该配置可以传递,即xml中加载新的xml文件,新的xml文件不必配置,仅需配置一次即可
xmlns:apollo="http://www.ctrip.com/schema/apollo"
http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd
2.日常开发使用apollo
1.本地配置apollo
1.1使用全局配置
在/opt/settings/server.properties(Mac/Linux)或C:\opt\settings\server.properties(Windows)文件添加配置:
apollo.meta=http://local-apollo.devops.kaishustory.com
apollo.cacheDir=修改为本地目录
1.2idea配置
启动参数中增加:-Dapollo.meta=你的apollo对应地址,从Apollo对应地址读取配置。
本地缓存路径修改:-Dapollo.cacheDir=/Users/${mac username}/Downloads/apollo.cacheDir,注意需要修改此路径。
1.3本地缓存配置:
Apollo客户端会把从服务端获取到的配置在本地文件系统缓存一份,用于在遇到服务不可用,或网络不通的时候,依然能从本地恢复配置,不影响应用正常运行。
本地缓存路径默认位于以下路径,所以请确保/opt/data
或C:\opt\data\
目录存在,且应用有读写权限。
Mac/Linux: /opt/data/{appId}/config-cache
Windows: C:\opt\data\{appId}\config-cache
本地配置文件会以下面的文件名格式放置于本地缓存路径下:
{appId}+{cluster}+{namespace}.properties
文件内容以properties格式存储,比如如果有两个key,一个是name,另一个是password,那么文件内容就是如下格式:
name=root
password=123456
自定义缓存路径
1.0.0版本开始支持以下方式自定义缓存路径,按照优先级从高到低分别为:
通过Java System Property apollo.cacheDir
a.可以通过Java的System Property apollo.cacheDir
来指定
b.在Java程序启动脚本中,可以指定-Dapollo.cacheDir=/opt/data/some-cache-dir
c.
如果是运行jar文件,需要注意格式是java -Dapollo.cacheDir=/opt/data/cacheDir -jar xxx.jar
d. 通过程序指定,如System.setProperty("apollo.cacheDir", "/opt/data/some-cache-dir")
1.4单元测试
引入pom文件
com.ctrip.framework.apollo
apollo-mockserver
1.1.0
在resource下防治mock数据,约定名称为mockdata-你的namespace.properties
编写测试类
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestConfiguration.class)
public class SpringIntegrationTest {
// 启动apollo的mockserver
@ClassRule
public static EmbeddedApollo embeddedApollo = new EmbeddedApollo();
@Test
@DirtiesContext
public void testPropertyInject(){
assertEquals("key1", testBean.key1);
assertEquals("key2", testBean.key2);
}
@Test
@DirtiesContext
public void testListenerTriggeredByAdd() throws InterruptedException, ExecutionException, TimeoutException {
String namespace = "";
embeddedApollo.addOrModifyPropery(namespace,"key","value");
ConfigChangeEvent changeEvent = testBean.futureData.get(5000, TimeUnit.MILLISECONDS);
assertEquals(namespace, changeEvent.getNamespace());
assertEquals("value", changeEvent.getChange("key").getNewValue());
}
@EnableApolloConfig("application")
@Configuration
static class TestConfiguration{
@Bean
public TestBean testBean(){
return new TestBean();
}
}
static class TestBean{
@Value("${key1}")
String key1;
@Value("${key2}")
String key2;
SettableFuture futureData = SettableFuture.create();
@ApolloConfigChangeListener("namespace")
private void onChange(ConfigChangeEvent changeEvent) {
futureData.set(changeEvent);
}
}
}