【你好Hystrix】一:Hystrix的动态配置-整合Archaius

前言

关于Hystrix我们就不做过多的介绍,大部分的同学都是在接触SC、SB之前都在项目中使用它。该项目目前处于维护阶段 在官网推荐我们使用Resilience4J, 它也是SC目前对熔断的默认支持。所以也不会对Hystrix做过多的介绍。主要对:配置、指标收集、断路器的实现等几个部分做一下介绍。

HystrixProperty

  • HystrixProperty:是在Archaius的基础上的扩展避免出现强依赖。它定义了Hystrix获取属性的一个方式,只有一个get()方法。
  • HystrixDynamicProperty:不言而喻 是hystrix对动态属性的定义,该接口增加了addCallback()方法和getName()方法。
  • ArchaiusDynamicProperty:这个实现很重要,使用桥接模式来整合Archaius

这个方法无法直接使用。PropertyWrapper 这个类就是 Archaius的一个比较核心的类 大部分的动态属性都是通过他来扩展的。ArchaiusDynamicProperty重写了HystrixDynamicPropertyget(),而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();
    }
}
  • StringDynamicPropertyIntegerDynamicProperty
    LongDynamicPropertyBooleanDynamicProperty均实现了ArchaiusDynamicProperty 实现相对简单。了解Archaius的都知道 其实在Archaius内部也有类似的实现 如DynamicIntPropertyDynamicDoubleProperty等等。但是Hystrix并没有选择使用,这里还是为了配合HystrixDynamicProperty来进行解耦。

HystrixDynamicProperties

HystrixDynamicProperties 可以认为是对动态属性的管理 对用户释放的一个接口,通过该接口可以获取各种类型的HystrixProperty

HystrixDynamicPropertiesArchaius

HystrixDynamicPropertiesArchaius 从名字都能看出是对Archaius的集成。我们上面所说的StringDynamicPropertyIntegerDynamicPropertyLongDynamicPropertyBooleanDynamicProperty 都是在该类的内部定义。它的实现非常简单仅仅是使用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。所以ArchaiusHystrix的默认配置实现, 但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;
    }

到这其实HystrixArchaius的整合就完成了。所以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使用HystrixPropertyHystrixDynamicProperty来获取一个配置
  • Hystrix使用HystrixDynamicProperties来定义配置的具体的底层实现,如其子类HystrixDynamicPropertiesArchaius用来整合Archaius的实现。HystrixDynamicPropertiesSystemProperties用来整合系统配置。
  • Hystrix使用HystrixPropertiesChainedProperty可以获取一个链式配置,Hystrix所有的属性几乎都是基于链式配置的。所以该类在HystrixXXXXProperties配置容器中大量使用。而HystrixXXXXProperties也是Hystrix最终提供使用者的配置管理集。
  • Hystrix使用HystrixPropertiesFactorygetXXXXProperties方法们来获取一个配置容器 该容器管理着Hystrix相应模块的所有的配置值。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值