Rely on the following

<dependency>
    <groupId>com.netflix.hystrix</groupId>
    <artifactId>hystrix-core</artifactId>
    <version>1.5.18</version>
</dependency>
Copy the code

What is the Hystrix

2018.11 released the last version, currently dealing with the maintenance phase, no upgrade version

  • USES:

    • Stop the cascading fault. Fallback and elegant downgrades, Fail Fast and quick recoveries
    • Monitor and configure real-time changes
    • Resource isolation. Partial unavailability does not cause system unavailability
  • Scenario: On the commodity list interface, data such as red packets, prices, and labels need to be obtained. You can give this guy a thread pool. If the thread pool is full, the non-commodity list interface of the current service is not affected

  • Use: the framework of main use Rxjava hystrix, fit may refer to: www.jianshu.com/p/5e93c9101…

Hystrix configuration is external and dynamic

Hystrix their implements a configuration interface HystrixProperty (general Config:com.net fix useless netflix. Config. The Property)

public interface HystrixProperty<T> {
    // get gets the attribute method
    public T get(a);

    /** * HystrixProperty is produced directly by the Factory without any third party dependencies. * - The core subinterface is (explained below) : HystrixDynamicProperty */
    public static class Factory {
        public static <T> HystrixProperty<T> asProperty(final T value) {
          return new HystrixProperty<T>() {
            @Override
            public T get(a) { returnvalue; }}; }/ /... That leaves various other methods to get the property asProperty}}Copy the code

HystrixDynamicProperty

Hystrix implements dynamic properties mainly through the HystrixDynamicProperty interface. This corresponds to two implementation classes for HystrixDynamicProperties:

  • Hystrix also manages property classes in a variety of ways, including an Util class that manages individual properties, but currently only supports String, Integer, Long, and Boolean
public interface HystrixDynamicProperties {
  public HystrixDynamicProperty<String> getString(String name, String fallback);
  public HystrixDynamicProperty<Integer> getInteger(String name, Integer fallback);
  public HystrixDynamicProperty<Long> getLong(String name, Long fallback);
  public HystrixDynamicProperty<Boolean> getBoolean(String name, Boolean fallback);
  public static class Util {
    public static <T> HystrixDynamicProperty<T> getProperty( HystrixDynamicProperties properties, String name, T fallback, Class
       
         type)
        {
      return (HystrixDynamicProperty<T>) doProperty(properties, name, fallback, type);
    }
    private staticHystrixDynamicProperty<? > doProperty( HystrixDynamicProperties delegate, String name, Object fallback, Class<? > type) {// Supports only four types: String, Integer, Long, and Boolean
      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 newIllegalStateException(); }}}Copy the code

The delegate.getxxxx () in HystrixDynamicProperties is implemented in the following two ways

  • HystrixDynamicPropertiesSystemProperties:

Obtained via system.getProperty (), which naturally supports dynamic, but does not support callback callbacks and externalized configurations

public final class HystrixDynamicPropertiesSystemProperties implements HystrixDynamicProperties {
    public HystrixDynamicPropertiesSystemProperties(a) {}
    private static class LazyHolder {
        private static final HystrixDynamicPropertiesSystemProperties INSTANCE = new HystrixDynamicPropertiesSystemProperties();
    }
    public static HystrixDynamicProperties getInstance(a) { return LazyHolder.INSTANCE; }
    @Override
    public HystrixDynamicProperty<Integer> getInteger(final String name, final Integer fallback) {
        return new HystrixDynamicProperty<Integer>() {
            @Override
            public String getName(a) { return name; }
            @Override
            public Integer get(a) {// integer.getInteger finally calls System.getProperty()
                return Integer.getInteger(name, fallback);
            }
            @Override
            public void addCallback(Runnable callback) {}}; }/ /... The rest of the String, Long, and Boolean types are not listed and are used the same way
}
Copy the code
  • HystrixDynamicPropertiesArchaius (Archaius netflix your configuration management repository) :

Netfix’s own configuration management library, supports dynamic

public class HystrixDynamicPropertiesArchaius implements HystrixDynamicProperties {
    @Override
    public HystrixDynamicProperty<String> getString(String name, String fallback) {
        return new StringDynamicProperty(name, fallback);
    }
    @Override
    public HystrixDynamicProperty<Integer> getInteger(String name, Integer fallback) {
        return new IntegerDynamicProperty(name, fallback);
    }
   / /... Omit other types String, Long, and Boolean
    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(a) { returngetValue(); }}private static class IntegerDynamicProperty extends ArchaiusDynamicProperty<Integer> {
        protected IntegerDynamicProperty(String propName, Integer defaultValue) { super(propName, defaultValue); }
        /** prop.getInteger calls ConcurrentHashMap. See parsing **/ below
        @Override
        public Integer getValue(a) { returnprop.getInteger(defaultValue); }}/ /... Omit other types String, Long, and Boolean
}
Copy the code

Archaius differs from System(system.getProperty ()) in that it reads data from the configuration file

  1. Get the IntegerDynamicProperty by calling the super() method
protected IntegerDynamicProperty(String propName, Integer defaultValue) {
   super(propName, defaultValue);// In ArchaiusDynamicProperty
}
Copy the code
  1. Tracing calls to the PropertyWrapper class and initialization operations such as obtaining the corresponding singleton and assigning default values are performed
public abstract class PropertyWrapper<V> {
  protected PropertyWrapper(String propName, V defaultValue) {
    / /!!!!!! Focus on this, where is the entry to get the value of the property based on the property name
    this.prop = DynamicProperty.getInstance(propName);
    this.defaultValue = defaultValue;
    / /... Initial initialization operation, omitted}}Copy the code
  1. DynamicProperty. In the process of the getInstance for instance, may update the attribute value
public class DynamicProperty {
   // get the corresponding DynamicProperty instance DynamicProperty based on the property name
  public static DynamicProperty getInstance(String propName) {
    if (dynamicPropertySupportImpl == null) {
      DynamicPropertyFactory.getInstance();
    }
    // 1 retrieves the attribute value from the cache
    DynamicProperty prop = ALL_PROPS.get(propName);
    if (prop == null) {
        // 2 If not found, try to update (new DynamicProperty(propName) has an update operation)
      prop = new DynamicProperty(propName);
      // Then set the new property value
      DynamicProperty oldProp = ALL_PROPS.putIfAbsent(propName, prop);
      if(oldProp ! =null) { prop = oldProp; }}returnprop; }}Copy the code
  1. Finally, let’s look at how to update and pull a value. The core is updateValue()
public class DynamicProperty {
  private DynamicProperty(String propName) {
    this.propName = propName;
    updateValue();
  }
  // !!!! Finally can see were obtained through a dynamicPropertySupportImpl. Then how did you get this,
  // !!!! The key is how do you bind it, and I'm going to talk about how do you bind it
  private boolean updateValue(a) {
    String newValue;
    try {
      if(dynamicPropertySupportImpl ! =null) {
          // Call this instance method to get the property value
        newValue = dynamicPropertySupportImpl.getString(propName);
      } else {
        return false; }}catch (Exception e) {
      logger.error("Unable to update property: " + propName, e);
      return false;
    }
    returnupdateValue(newValue); }}Copy the code

How does Hystrix select the right configuration class to load

This step will explain on step dynamicPropertySupportImpl instance is how to choose? Actually is ultimately returned back by DynamicPropertyFactory production configuration object, and then assigned to dynamicPropertySupportImpl see below how he this configuration object is instantiated

  1. When HystrixPlugins are initialized, the parse dynamic properties are loaded
public class HystrixPlugins {
  private HystrixPlugins(ClassLoader classLoader, LoggerSupplier logSupplier) {
    this.classLoader = classLoader; dynamicProperties = resolveDynamicProperties(classLoader, logSupplier); }}Copy the code
  1. Let’s see if there’s any custom, so if there is, load classForName. Then use SPI to scan, and if it does, use the first configuration class. Look again at HystrixDynamicPropertiesArchaius, HystrixDynamicPropertiesSystemProperties are used if there is no or failure load
public class HystrixPlugins {
  private static HystrixDynamicProperties resolveDynamicProperties(ClassLoader classLoader, LoggerSupplier logSupplier) {
    / / the first step: first to see how didn't set properties: "hystrix. Plugin. HystrixDynamicProperties. Implementation", if you have it with a custom attribute class
    HystrixDynamicProperties hp = getPluginImplementationViaProperties(HystrixDynamicProperties.class,
            HystrixDynamicPropertiesSystemProperties.getInstance());
    if(hp ! =null) {
      logSupplier.getLogger().debug(
              "Created HystrixDynamicProperties instance from System property named "
                      + "\"hystrix.plugin.HystrixDynamicProperties.implementation\". Using class: {}",
              hp.getClass().getCanonicalName());
      return hp;
    }
    // Step 2: scan with SPI's loader, get the first one and return
    hp = findService(HystrixDynamicProperties.class, classLoader);
    if(hp ! =null) {
      logSupplier.getLogger()
              .debug("Created HystrixDynamicProperties instance by loading from ServiceLoader. Using class: {}",
                      hp.getClass().getCanonicalName());
      return hp;
    }
    / / step 3: look at HystrixDynamicPropertiesArchaius the parsing success, success is just use this attribute configuration class
    hp = HystrixArchaiusHelper.createArchaiusDynamicProperties();
    if(hp ! =null) {
      logSupplier.getLogger().debug("Created HystrixDynamicProperties. Using class : {}",
              hp.getClass().getCanonicalName());
      return hp;
    }
    GetProperty () = system.getProperty () = system.getProperty (
    hp = HystrixDynamicPropertiesSystemProperties.getInstance();
    logSupplier.getLogger().info("Using System Properties for HystrixDynamicProperties! Using class: {}",
            hp.getClass().getCanonicalName());
    returnhp; }}Copy the code

See this step, is there a bit more meng force! Oh, turns out we haven’t figured out when his profile was loaded in, or which profile it was. Don’t panic. Here we go

How does the configuration information load in

Hystrix has a ConfigurationManager that is called when the initial configuration is loaded (it is loaded from config.properties by default, if you need to add configuration information please add it here). The core method steps are as follows:

  1. Get the System configuration (loaded in with system.getProperties ())
  2. Load data from the configuration file
public class ConfigurationManager {
    / /... Other logical elisions
    public static AbstractConfiguration getConfigInstance(a) {
        if (instance == null && !Boolean.getBoolean(DynamicPropertyFactory.DISABLE_DEFAULT_CONFIG)) {
            synchronized (ConfigurationManager.class) {
                if (instance == null) {
                    instance = new ConcurrentCompositeConfiguration();
                    if(! Boolean.getBoolean(DynamicPropertyFactory.DISABLE_DEFAULT_SYS_CONFIG)) {// Step 1: Get the System configuration (load it all in with system.getProperties ())
                        SystemConfiguration sysConfig = new SystemConfiguration();
                        ((ConcurrentCompositeConfiguration) instance).addConfiguration(sysConfig, DynamicPropertyFactory.SYS_CONFIG_NAME);
                        try {
                            // Step 2: Load data from the default config.properties file
                            / / and then see how didn't set archaius configurationSource. AdditionalUrls attribute, if there are also from this file to load dynamic configuration
                            // Finally, a long poll is opened, with cached data refreshed every minute by default
                            DynamicURLConfiguration defaultURLConfig = new DynamicURLConfiguration();
                            ((ConcurrentCompositeConfiguration) instance).addConfiguration(defaultURLConfig, DynamicPropertyFactory.URL_CONFIG_NAME);
                        } catch (Throwable e) {
                            logger.warn("Failed to create default dynamic configuration", e); } } registerConfigBean(); }}}returninstance; }}Copy the code

The code for dynamically configuring the long poll refresh is as follows

/ / position: DynamicURLConfiguration. Java
public DynamicURLConfiguration(a) {
    URLConfigurationSource source = new URLConfigurationSource();
    if(source.getConfigUrls() ! =null && source.getConfigUrls().size() > 0) {
        startPolling(source, newFixedDelayPollingScheduler()); }}/ / position: DynamicConfiguration. Java
public void startPolling(PolledConfigurationSource source, AbstractPollingScheduler scheduler) {
    this.scheduler = scheduler;
    this.source = source;
    init(source, scheduler);
    scheduler.startPolling(source, this);
}
Copy the code