Hystrix支持很多种方式用来获取配置属性,本地默认,自定义设置,统一配置中心等等,最后都是用的同样的代码进行抽象,本文主要进行解析获取配置的主要方法getProperty(),以HystrixCommandProperties的熔断有效开关为例
private final HystrixProperty<Boolean> circuitBreakerEnabled; // Whether circuit breaker should be enabled.
this.circuitBreakerEnabled = getProperty(propertyPrefix, key, "circuitBreaker.enabled", builder.getCircuitBreakerEnabled(), default_circuitBreakerEnabled);
返回值都用HystrixProperty进行抽象表示,获取属性结果是get()方法;
private static HystrixProperty<Boolean> getProperty(String propertyPrefix, HystrixCommandKey key, String instanceProperty, Boolean builderOverrideValue, Boolean defaultValue) {
return forBoolean()
.add(propertyPrefix + ".command." + key.name() + "." + instanceProperty, builderOverrideValue)
.add(propertyPrefix + ".command.default." + instanceProperty, defaultValue)
.build();
}
private static <T> ChainBuilder<T> forType(final Class<T> type) {
return new ChainBuilder<T>() {
@Override
protected Class<T> getType() {
return type;
}
};
}
public static ChainBuilder<Boolean> forBoolean() {
return forType(Boolean.class);
}
初始化ChainBuilder对象,开始add对应的属性,这里的顺序很重要,优先级从高到低,当第一个有值的话就会直接返回。
public ChainBuilder<T> add(String name, T defaultValue) {
properties.add(getDynamicProperty(name, defaultValue, getType()));
return this;
}
public HystrixDynamicProperty<T> build() {
if (properties.size() < 1) throw new IllegalArgumentException();
if (properties.size() == 1) return properties.get(0);
List<HystrixDynamicProperty<T>> reversed =
new ArrayList<HystrixDynamicProperty<T>>(properties);
Collections.reverse(reversed);
ChainProperty<T> current = null;
for (HystrixDynamicProperty<T> p : reversed) {
if (current == null) {
current = new ChainProperty<T>(p);
}
else {
current = new ChainProperty<T>(p, current);
}
}
return new ChainHystrixProperty<T>(current);
}
获取动态属性配置类,该类会获取当前环境的配置来源,本地默认,自定义设置,统一配置中心等等,一般默认的话就是HystrixDynamicPropertiesSystemProperties,获取属性就是调用的System.getProperty(nm)
private static <T> HystrixDynamicProperty<T> getDynamicProperty(String propName, T defaultValue, Class<T> type) {
HystrixDynamicProperties properties = HystrixPlugins.getInstance().getDynamicProperties();
HystrixDynamicProperty<T> p = HystrixDynamicProperties.Util.getProperty(properties, propName, defaultValue, type);
return p;
}
获取因为不同的动态属性实现类实现了相同的接口,在这里就直接通过对应的实现类进行获取,
public static <T> HystrixDynamicProperty<T> getProperty(
HystrixDynamicProperties properties, String name, T fallback, Class<T> type) {
return (HystrixDynamicProperty<T>) doProperty(properties, name, fallback, type);
}
private static HystrixDynamicProperty<?> doProperty(
HystrixDynamicProperties delegate,
String name, Object fallback, Class<?> type) {
if(type == String.class) {
return delegate.getString(name, (String) fallback);
}
else if (type == Integer.class) {
return delegate.getInteger(name, (Integer) fallback);
}
else if (type == Long.class) {
return delegate.getLong(name, (Long) fallback);
}
else if (type == Boolean.class) {
return delegate.getBoolean(name, (Boolean) fallback);
}
throw new IllegalStateException();
}
HystrixDynamicPropertiesSystemProperties的get方法如下。返回动态属性HystrixDynamicProperty并把它加入到ChainBuilder集合 private List<HystrixDynamicProperty<T>> properties = new ArrayList<HystrixDynamicProperty<T>>();
public HystrixDynamicProperty<Boolean> getBoolean(final String name, final Boolean fallback) {
return new HystrixDynamicProperty<Boolean>() {
@Override
public String getName() {
return name;
}
@Override
public Boolean get() {
if (System.getProperty(name) == null) {
return fallback;
}
return Boolean.getBoolean(name);
}
@Override
public void addCallback(Runnable callback) {
}
};
}
最后开始执行build()方法,因为最先访问的对象肯定是最外层的对象,刚开始创建的对象肯定是最里层的对象,所以这个时候需要把整个集合进行倒序排列Collections.reverse(reversed);开始用ChainProperty包装动态属性,他有两个构造函数,分别对应最里层对象和外层对象,
private static class ChainProperty<T> extends ChainLink<T> {
private final HystrixDynamicProperty<T> sProp;
public ChainProperty(HystrixDynamicProperty<T> sProperty) {
super();
sProp = sProperty;
}
public ChainProperty(HystrixDynamicProperty<T> sProperty, ChainProperty<T> next) {
super(next); // setup next pointer
sProp = sProperty;
sProp.addCallback(new Runnable() {
@Override
public void run() {
logger.debug("Property changed: '{} = {}'", getName(), getValue());
checkAndFlip();
}
});
checkAndFlip();
}
@Override
public boolean isValueAcceptable() {
return (sProp.get() != null);
}
@Override
protected T getValue() {
return sProp.get();
}
@Override
public String getName() {
return sProp.getName();
}
}
当设置第一个属性时,设置父类的next为null,在子类中保存HystrixDynamicProperty<T> sProp
public ChainLink() {
next = null;
pReference = new AtomicReference<ChainLink<T>>(this);
callbacks = new ArrayList<Runnable>();
}
当设置第二个属性时,设置父类next为前一个属性对象,保存当前属性对象,设置回调函数addCallback,本例无回调函数,查看当前动态属性值是否存在,执行get方法,也就是HystrixDynamicPropertiesSystemProperties的getBoolean方法,如果有值的话,设置AtomicReference<ChainLink<T>> pReference为自己,否则设置为里层对象。最后用对象ChainHystrixProperty包装
public boolean isValueAcceptable() {
return (sProp.get() != null);
}
protected void checkAndFlip() {
// in case this is the end node
if (next == null) {
pReference.set(this);
return;
}
if (this.isValueAcceptable()) {
logger.debug("Flipping property: {} to use its current value: {}", getName(), getValue());
pReference.set(this);
} else {
logger.debug("Flipping property: {} to use NEXT property: {}", getName(), next);
pReference.set(next);
}
for (Runnable r : callbacks) {
r.run();
}
}
开始get获取对象this.properties.circuitBreakerEnabled().get(),ChainHystrixProperty#get()=>ChainProperty#get()=>ChainLink#get(),判断当前的原子引用是否是最外层对象,如果是的话直接调用getValue方法,也就是直接调用HystrixDynamicProperty#get(),否则递归里面的对象,最后获取到最后的属性值返回。
public T get() {
if (pReference.get() == this) {
return this.getValue();
} else {
return pReference.get().get();
}
}