在之前的系列讲过Hystrix的核心实现源码,多次提及到Archaius(Netflix公司开源项目之一),其实Netflix的所有组件都是通过它获取配置。Archaius主要用于多配置存储的动态获取,基于对apache common configuration类库的扩展。本文基于hystrix-core 1.4.26(最新的1.5.18会有些差别)。
//比如Hystrix有使用
public class HystrixPlugins {
private static Object getPluginImplementationViaArchaius(Class> pluginClass) {
String classSimpleName = pluginClass.getSimpleName();
// Check Archaius for plugin class.
String propertyName = "hystrix.plugin." + classSimpleName + ".implementation";
//这里有使用
String implementingClass = DynamicPropertyFactory.getInstance().getStringProperty(propertyName, null).get();
if (implementingClass != null) {
...
}
}
//配置管理类核心实现
public class DynamicPropertyFactory {
private static DynamicPropertyFactory instance = new DynamicPropertyFactory();
public DynamicStringProperty getStringProperty(String propName, String defaultValue) {
return this.getStringProperty(propName, defaultValue, (Runnable)null);
}
public DynamicStringProperty getStringProperty(String propName, String defaultValue, Runnable propertyChangeCallback) {
checkAndWarn(propName);
DynamicStringProperty property = new DynamicStringProperty(propName, defaultValue);
addCallback(propertyChangeCallback, property);
return property;
}
}
它有如下一些特性:
com.netflix.archaius
archaius-core
0.6.0
有两种方法可以让Archaius通过使用本地配置文件向应用程序提供动态属性来实现开箱即用的工作。
DynamicLongProperty timeToWait = DynamicPropertyFactory.getInstance().getLongProperty("lock.waitTime", 1000);//默认值为1000
timeToWait.get();//获取值
默认的:Archaius会每一分钟去重新加载下属性配置,多属性文件时的属性会覆盖(最后读到的属性会覆盖前面相同的属性)
Operation | HTTP action | Notes |
archaius.configurationSource.defaultFileName | 指定Archaius默认加载的配置源属性文件名,默认:classpath:config.properties | config.properties |
archaius.fixedDelayPollingScheduler.initialDelayMills | 延迟加载,默认30秒 | 30000 |
archaius.fixedDelayPollingScheduler.delayMills | 两次属性读取时间间隔,默认1分钟 | 60000 |
默认情况下,Archius使用一组URL作为配置源,并以固定的延迟对其进行轮询。但是,您也可以提供自己的配置源和/或轮询调度程序。例如,您可以从关系数据库、分布式键值存储(如Cassandra)或第三方服务(如AWS SimpleDB)定义自己的配置源。
public class DBConfigurationSource implements PolledConfigurationSource {
// ...
@Override
public PollResult poll(boolean initial, Object checkPoint)
throws Exception {
// implement logic to retrieve properties from DB
}
}
public class MyScheduler extends AbstractPollingScheduler {
// ...
@Override
protected synchronized void schedule(Runnable runnable) {
// schedule the runnable
}
@Override
public void stop() {
// stop the scheduler
}
}
PolledConfigurationSource source = ...
AbstractPollingScheduler scheduler = ...
DynamicConfiguration configuration = new DynamicConfiguration(source, scheduler);
ConfigurationManager.install(configuration);
DynamicStringProperty myprop = DynamicPropertyFactory.getInstance().getStringProperty(...);
DeploymentContext定义一组基于部署上下文的属性。这些属性的值是可选的,可以是任何字符串。例如,环境是部署上下文的一个属性,可以是“prod”、“test”或对组织有意义的任何其他字符串,简单的讲就是多环境上可以使用。
此实现需要指向包含配置属性层次结构的zk根父节点的路径。所有服务器都将收到zk watcher回调,并自动更新其值,类似于其他动态配置源。
String zkConfigRootPath = "/[my-app]/config";
CuratorFramework client CuratorFrameworkFactory.newClient(zkConnectionString, new ExponentialBackoffRetry(1000, 3));
ZooKeeperConfigurationSource zkConfigSource = new ZooKeeperConfigurationSource(client, zkConfigRootPath);
zkConfigSource.start();
DynamicWatchedConfiguration zkDynamicConfig = new DynamicWatchedConfiguration(zkConfigSource);
ConfigurationManager.install(zkDynamicConfig);
//读取节点属性值/[my-app]/config/com.fluxcapacitor.my.property
String myProperty = DynamicPropertyFactory.getInstance().getStringProperty("com.fluxcapacitor.my.property", "").get();
应用程序可以定义应用于动态属性值的验证规则。如果在更新动态属性期间验证失败,则将引发RuntimeException,并且动态属性的值将保持不变。
DynamicIntProperty validatedProp = new DynamicIntProperty("abc", 0) {
@Override
public void validate(String newValue) {
if (Integer.parseInt(newValue) < 0) {
throw new ValidationException("Cannot be negative");
}
}
};
总结,关于java的配置管理类库,Archaius是其中一个实现版本,spring-boot 也有自己的实现,它叫Spring Boot external config。由此可以看出,在spring cloud netflix的组件时要特别关注这一点!