目录
前言
关于Hystrix我们就不做过多的介绍,大部分的同学都是在接触SC、SB之前都在项目中使用它。该项目目前处于维护阶段 在官网推荐我们使用Resilience4J
, 它也是SC目前对熔断的默认支持。所以也不会对Hystrix
做过多的介绍。主要对:配置、指标收集、断路器的实现等几个部分做一下介绍。
HystrixProperty
HystrixProperty
:是在Archaius
的基础上的扩展避免出现强依赖。它定义了Hystrix
获取属性的一个方式,只有一个get()
方法。HystrixDynamicProperty
:不言而喻 是hystrix对动态属性的定义,该接口增加了addCallback()
方法和getName()
方法。ArchaiusDynamicProperty
:这个实现很重要,使用桥接模式来整合Archaius
这个方法无法直接使用。PropertyWrapper
这个类就是 Archaius
的一个比较核心的类 大部分的动态属性都是通过他来扩展的。ArchaiusDynamicProperty
重写了HystrixDynamicProperty
的get()
,而get方法内部的实现是Archaius
的实现了,这样就把它整合进来了。
private abstract static class ArchaiusDynamicProperty<T>
extends PropertyWrapper<T> implements HystrixDynamicProperty<T> {
protected ArchaiusDynamicProperty(String propName, T defaultValue) {
super(propName, defaultValue);
}
@Override
public T get() {
return getValue();
}
}
StringDynamicProperty
、IntegerDynamicProperty
、
LongDynamicProperty
、BooleanDynamicProperty
均实现了ArchaiusDynamicProperty
实现相对简单。了解Archaius
的都知道 其实在Archaius
内部也有类似的实现 如DynamicIntProperty
、DynamicDoubleProperty
等等。但是Hystrix
并没有选择使用,这里还是为了配合HystrixDynamicProperty
来进行解耦。
HystrixDynamicProperties
HystrixDynamicProperties
可以认为是对动态属性的管理 对用户释放的一个接口,通过该接口可以获取各种类型的HystrixProperty
HystrixDynamicPropertiesArchaius
HystrixDynamicPropertiesArchaius
从名字都能看出是对Archaius
的集成。我们上面所说的StringDynamicProperty
、IntegerDynamicProperty
、LongDynamicProperty
、BooleanDynamicProperty
都是在该类的内部定义。它的实现非常简单仅仅是使用ArchaiusDynamicProperty
的不同的子类来做代理。
@Override
public HystrixDynamicProperty<String> getString(String name, String fallback) {
return new StringDynamicProperty(name, fallback);
}
/**
* @ExcludeFromJavadoc
*/
@Override
public HystrixDynamicProperty<Integer> getInteger(String name, Integer fallback) {
return new IntegerDynamicProperty(name, fallback);
}
/**
* @ExcludeFromJavadoc
*/
@Override
public HystrixDynamicProperty<Long> getLong(String name, Long fallback) {
return new LongDynamicProperty(name, fallback);
}
/**
* @ExcludeFromJavadoc
*/
@Override
public HystrixDynamicProperty<Boolean> getBoolean(String name, Boolean fallback) {
return new BooleanDynamicProperty(name, fallback);
}
我们再使用Hystrix的时候不应该直接使用该类,而Hystrix的HystrixPlugins
为我们提供了一个获取它的方法:HystrixPlugins.getInstance().getDynamicProperties()
。
HystrixPlugins.getDynamicProperties()
单例模式创建HystrixPlugins
private static class LazyHolder { private static final HystrixPlugins INSTANCE = HystrixPlugins.create();
}
public static HystrixPlugins getInstance() {
return LazyHolder.INSTANCE;
}
private HystrixPlugins(ClassLoader classLoader, LoggerSupplier logSupplier) {
this.classLoader = classLoader;
dynamicProperties = resolveDynamicProperties(classLoader, logSupplier);
}
这个应该是单例模式的正确创建姿势。再构造方法中解析动态属性的实现也就是找HystrixDynamicProperties
的实现类,通过SPI方式。如果找不到就默认实例化一个HystrixDynamicPropertiesArchaius
。所以Archaius
是Hystrix
的默认配置实现, 但Hystrix
却不强依赖它(注意包还是强依赖的)。这里如果能把这一块对Archaius的整合提取出来单独一个模块就更完美了,这样就不用强依赖Archaius
的包了。我们看一下getDynamicProperties()
方法代码:
private static HystrixDynamicProperties resolveDynamicProperties(ClassLoader classLoader, LoggerSupplier logSupplier) {
HystrixDynamicProperties hp = getPluginImplementationViaProperties(HystrixDynamicProperties.class,
HystrixDynamicPropertiesSystemProperties.getInstance());
if (hp != null) {
return hp;
}
hp = findService(HystrixDynamicProperties.class, classLoader);
if (hp != null) {
return hp;
}
//默认创建HystrixDynamicPropertiesArchaius实例
hp = HystrixArchaiusHelper.createArchaiusDynamicProperties();
if (hp != null) {
return hp;
}
hp = HystrixDynamicPropertiesSystemProperties.getInstance();
return hp;
}
到这其实Hystrix
对Archaius
的整合就完成了。所以HystrixDynamicPropertiesArchaius
是整合Archaius
的桥梁。
Hystrix的链式属性HystrixPropertiesChainedProperty
先来看一段代码
HystrixDynamicProperty<String> personNameProperty = HystrixPropertiesChainedProperty.forString()
.add("hystrix.command.coredy.personName", null)
.add("hystrix.command.default.personName", "coredy")
.build();
System.out.println(personNameProperty.get());
上面代码如果我们在config.properties中配置了hystrix.command.coredy.personName
就会输出该值,否则输出默认值。这就一下子有点Hystrix
配置的影子了。 下面来看看是如何做到的。
为了搞清内部实现 先来对几个重要的类来说明.
ChainLink
:链环 可以理解为链表的一个节点,无法直接使用
//保存当前节点的原子引用对象
private final AtomicReference<ChainLink<T>> pReference;
//下一个节点的引用
private final ChainLink<T> next;
//节点变化的回调函数
private final List<Runnable> callbacks;
//以下为子类需实现的方法
public abstract String getName();
protected abstract T getValue();
public abstract boolean isValueAcceptable();
ChainProperty
: ChainLink的唯一实现类,内部保存了一个HystrixDynamicProperty
无法直接使用
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);
sProp = sProperty;
sProp.addCallback(new Runnable() {
public void run() {
checkAndFlip();
}
});
checkAndFlip();
}
@Override
public boolean isValueAcceptable() {
return (sProp.get() != null);
}
@Override
protected T getValue() {
return sProp.get();
}
@Override
public String getName() {
return sProp.getName();
}
}
ChainHystrixProperty
:该类作用就是将ChainProperty
转换成HystrixDynamicProperty
private static class ChainHystrixProperty<T> implements HystrixDynamicProperty<T> {
private final ChainProperty<T> property;
}
需要注意的是上面的类均是私有的 不可直接使用。介绍完上面的几个核心类之后, 还需要对HystrixPropertiesChainedProperty
类的几个静态方法加以介绍。
private static <T> ChainBuilder<T> forType(final Class<T> type) {
return new ChainBuilder<T>() {
@Override
protected Class<T> getType() {
return type;
}
};
}
public static ChainBuilder<String> forString() {
return forType(String.class);
}
public static ChainBuilder<Integer> forInteger() {
return forType(Integer.class);
}
public static ChainBuilder<Boolean> forBoolean() {
return forType(Boolean.class);
}
public static ChainBuilder<Long> forLong() {
return forType(Long.class);
}
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;
}
上面的 forXXX
方法均是构建ChainBuilder
的方法,所以我们可以直接使用。
getDynamicProperty
该方法是一个工具方法 获取一个HystrixDynamicProperty
上面说了 HystrixPlugins.getInstance().getDynamicProperties()
默认是实例化一个HystrixDynamicPropertiesArchaius
。
通过build()
方法 就完全屏蔽了ChainLink
的用法。又变成对面向用户的接口HystrixDynamicProperty
只不过这个接口实现可能是ChainHystrixProperty
,注意这里是可能,因为 如果集合中如果只有一个动态属性的话 那么返回的就是HystrixDynamicProperty
的几个不同类型的实现了。
public HystrixDynamicProperty<T> build() {
if (properties.size() < 1) throw new IllegalArgumentException();
//properties是ChainBuilder保存的一个list用于存放HystrixDynamicProperty
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);
}
总结
对上面的内容做一个总结:
Hystrix
使用HystrixProperty
、HystrixDynamicProperty
来获取一个配置Hystrix
使用HystrixDynamicProperties
来定义配置的具体的底层实现,如其子类HystrixDynamicPropertiesArchaius
用来整合Archaius
的实现。HystrixDynamicPropertiesSystemProperties
用来整合系统配置。Hystrix
使用HystrixPropertiesChainedProperty
可以获取一个链式配置,Hystrix
所有的属性几乎都是基于链式配置的。所以该类在HystrixXXXXProperties
配置容器中大量使用。而HystrixXXXXProperties
也是Hystrix
最终提供使用者的配置管理集。Hystrix
使用HystrixPropertiesFactory
的getXXXXProperties
方法们来获取一个配置容器 该容器管理着Hystrix
相应模块的所有的配置值。