Talk about HystrixPropertiesStrategy

  hystrix

Order

This article mainly studies the HystrixPropertiesStrategy

HystrixPropertiesStrategy

hystrix-core-1.5.12-sources.jar! /com/netflix/hystrix/strategy/properties/HystrixPropertiesStrategy.java

/**
 * Abstract class with default implementations of factory methods for properties used by various components of Hystrix.
 * <p>
 * See {@link HystrixPlugins} or the Hystrix GitHub Wiki for information on configuring plugins: <a
 * href="https://github.com/Netflix/Hystrix/wiki/Plugins">https://github.com/Netflix/Hystrix/wiki/Plugins</a>.
 */
public abstract class HystrixPropertiesStrategy {

    /**
     * Construct an implementation of {@link HystrixCommandProperties} for {@link HystrixCommand} instances with {@link HystrixCommandKey}.
     * <p>
     * <b>Default Implementation</b>
     * <p>
     * Constructs instance of {@link HystrixPropertiesCommandDefault}.
     * 
     * @param commandKey
     *            {@link HystrixCommandKey} representing the name or type of {@link HystrixCommand}
     * @param builder
     *            {@link com.netflix.hystrix.HystrixCommandProperties.Setter} with default overrides as injected from the {@link HystrixCommand} implementation.
     *            <p>
     *            The builder will return NULL for each value if no override was provided.
     * @return Implementation of {@link HystrixCommandProperties}
     */
    public HystrixCommandProperties getCommandProperties(HystrixCommandKey commandKey, HystrixCommandProperties.Setter builder) {
        return new HystrixPropertiesCommandDefault(commandKey, builder);
    }

    /**
     * Cache key used for caching the retrieval of {@link HystrixCommandProperties} implementations.
     * <p>
     * Typically this would return <code>HystrixCommandKey.name()</code> but can be done differently if required.
     * <p>
     * For example, null can be returned which would cause it to not cache and invoke {@link #getCommandProperties} for each {@link HystrixCommand} instantiation (not recommended).
     * <p>
     * <b>Default Implementation</b>
     * <p>
     * Returns {@link HystrixCommandKey#name()}
     * 
     * @param commandKey command key used in determining command's cache key
     * @param builder builder for {@link HystrixCommandProperties} used in determining command's cache key
     * @return String value to be used as the cache key of a {@link HystrixCommandProperties} implementation.
     */
    public String getCommandPropertiesCacheKey(HystrixCommandKey commandKey, HystrixCommandProperties.Setter builder) {
        return commandKey.name();
    }

    /**
     * Construct an implementation of {@link HystrixThreadPoolProperties} for {@link HystrixThreadPool} instances with {@link HystrixThreadPoolKey}.
     * <p>
     * <b>Default Implementation</b>
     * <p>
     * Constructs instance of {@link HystrixPropertiesThreadPoolDefault}.
     * 
     * @param threadPoolKey
     *            {@link HystrixThreadPoolKey} representing the name or type of {@link HystrixThreadPool}
     * @param builder
     *            {@link com.netflix.hystrix.HystrixThreadPoolProperties.Setter} with default overrides as injected via {@link HystrixCommand} to the {@link HystrixThreadPool} implementation.
     *            <p>
     *            The builder will return NULL for each value if no override was provided.
     * 
     * @return Implementation of {@link HystrixThreadPoolProperties}
     */
    public HystrixThreadPoolProperties getThreadPoolProperties(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties.Setter builder) {
        return new HystrixPropertiesThreadPoolDefault(threadPoolKey, builder);
    }

    /**
     * Cache key used for caching the retrieval of {@link HystrixThreadPoolProperties} implementations.
     * <p>
     * Typically this would return <code>HystrixThreadPoolKey.name()</code> but can be done differently if required.
     * <p>
     * For example, null can be returned which would cause it to not cache and invoke {@link #getThreadPoolProperties} for each {@link HystrixThreadPool} instantiation (not recommended).
     * <p>
     * <b>Default Implementation</b>
     * <p>
     * Returns {@link HystrixThreadPoolKey#name()}
     *
     * @param threadPoolKey thread pool key used in determining thread pool's cache key
     * @param builder builder for {@link HystrixThreadPoolProperties} used in determining thread pool's cache key
     * @return String value to be used as the cache key of a {@link HystrixThreadPoolProperties} implementation.
     */
    public String getThreadPoolPropertiesCacheKey(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties.Setter builder) {
        return threadPoolKey.name();
    }

    /**
     * Construct an implementation of {@link HystrixCollapserProperties} for {@link HystrixCollapser} instances with {@link HystrixCollapserKey}.
     * <p>
     * <b>Default Implementation</b>
     * <p>
     * Constructs instance of {@link HystrixPropertiesCollapserDefault}.
     * 
     * @param collapserKey
     *            {@link HystrixCollapserKey} representing the name or type of {@link HystrixCollapser}
     * @param builder
     *            {@link com.netflix.hystrix.HystrixCollapserProperties.Setter} with default overrides as injected to the {@link HystrixCollapser} implementation.
     *            <p>
     *            The builder will return NULL for each value if no override was provided.
     * 
     * @return Implementation of {@link HystrixCollapserProperties}
     */
    public HystrixCollapserProperties getCollapserProperties(HystrixCollapserKey collapserKey, HystrixCollapserProperties.Setter builder) {
        return new HystrixPropertiesCollapserDefault(collapserKey, builder);
    }

    /**
     * Cache key used for caching the retrieval of {@link HystrixCollapserProperties} implementations.
     * <p>
     * Typically this would return <code>HystrixCollapserKey.name()</code> but can be done differently if required.
     * <p>
     * For example, null can be returned which would cause it to not cache and invoke {@link #getCollapserProperties} for each {@link HystrixCollapser} instantiation (not recommended).
     * <p>
     * <b>Default Implementation</b>
     * <p>
     * Returns {@link HystrixCollapserKey#name()}
     *
     * @param collapserKey collapser key used in determining collapser's cache key
     * @param builder builder for {@link HystrixCollapserProperties} used in determining collapser's cache key
     * @return String value to be used as the cache key of a {@link HystrixCollapserProperties} implementation.
     */
    public String getCollapserPropertiesCacheKey(HystrixCollapserKey collapserKey, HystrixCollapserProperties.Setter builder) {
        return collapserKey.name();
    }

    /**
     * Construct an implementation of {@link com.netflix.hystrix.HystrixTimerThreadPoolProperties} for configuration of the timer thread pool
     * that handles timeouts and collapser logic.
     * <p>
     * Constructs instance of {@link HystrixPropertiesTimerThreadPoolDefault}.
     *
     *
     * @return Implementation of {@link com.netflix.hystrix.HystrixTimerThreadPoolProperties}
     */
    public HystrixTimerThreadPoolProperties getTimerThreadPoolProperties() {
        return new HystrixPropertiesTimerThreadPoolDefault();
    }
}

Provides methods to get the properties of HystrixCommandProperties, HystrixThreadPoolProperties, HystrixCollapserProperties, Hystrixtimerthreadpoolproperties

HystrixCommandProperties

hystrix-core-1.5.12-sources.jar! /com/netflix/hystrix/HystrixCommandProperties.java

/**
 * Properties for instances of {@link HystrixCommand}.
 * <p>
 * Default implementation of methods uses Archaius (https://github.com/Netflix/archaius)
 */
public abstract class HystrixCommandProperties {
    private static final Logger logger = LoggerFactory.getLogger(HystrixCommandProperties.class);

    /* defaults */
    /* package */ static final Integer default_metricsRollingStatisticalWindow = 10000;// default => statisticalWindow: 10000 = 10 seconds (and default of 10 buckets so each bucket is 1 second)
    private static final Integer default_metricsRollingStatisticalWindowBuckets = 10;// default => statisticalWindowBuckets: 10 = 10 buckets in a 10 second window so each bucket is 1 second
    private static final Integer default_circuitBreakerRequestVolumeThreshold = 20;// default => statisticalWindowVolumeThreshold: 20 requests in 10 seconds must occur before statistics matter
    private static final Integer default_circuitBreakerSleepWindowInMilliseconds = 5000;// default => sleepWindow: 5000 = 5 seconds that we will sleep before trying again after tripping the circuit
    private static final Integer default_circuitBreakerErrorThresholdPercentage = 50;// default => errorThresholdPercentage = 50 = if 50%+ of requests in 10 seconds are failures or latent then we will trip the circuit
    private static final Boolean default_circuitBreakerForceOpen = false;// default => forceCircuitOpen = false (we want to allow traffic)
    /* package */ static final Boolean default_circuitBreakerForceClosed = false;// default => ignoreErrors = false 
    private static final Integer default_executionTimeoutInMilliseconds = 1000; // default => executionTimeoutInMilliseconds: 1000 = 1 second
    private static final Boolean default_executionTimeoutEnabled = true;
    private static final ExecutionIsolationStrategy default_executionIsolationStrategy = ExecutionIsolationStrategy.THREAD;
    private static final Boolean default_executionIsolationThreadInterruptOnTimeout = true;
    private static final Boolean default_executionIsolationThreadInterruptOnFutureCancel = false;
    private static final Boolean default_metricsRollingPercentileEnabled = true;
    private static final Boolean default_requestCacheEnabled = true;
    private static final Integer default_fallbackIsolationSemaphoreMaxConcurrentRequests = 10;
    private static final Boolean default_fallbackEnabled = true;
    private static final Integer default_executionIsolationSemaphoreMaxConcurrentRequests = 10;
    private static final Boolean default_requestLogEnabled = true;
    private static final Boolean default_circuitBreakerEnabled = true;
    private static final Integer default_metricsRollingPercentileWindow = 60000; // default to 1 minute for RollingPercentile 
    private static final Integer default_metricsRollingPercentileWindowBuckets = 6; // default to 6 buckets (10 seconds each in 60 second window)
    private static final Integer default_metricsRollingPercentileBucketSize = 100; // default to 100 values max per bucket
    private static final Integer default_metricsHealthSnapshotIntervalInMilliseconds = 500; // default to 500ms as max frequency between allowing snapshots of health (error percentage etc)
    //......
}

The default value of relevant parameter meter for hystrix command is provided.

HystrixThreadPoolProperties

hystrix-core-1.5.12-sources.jar! /com/netflix/hystrix/HystrixThreadPoolProperties.java

/**
 * Properties for instances of {@link HystrixThreadPool}.
 * <p>
 * Default implementation of methods uses Archaius (https://github.com/Netflix/archaius)
 *
 * Note a change in behavior in 1.5.7.  Prior to that version, the configuration for 'coreSize' was used to control
 * both coreSize and maximumSize.  This is a fixed-size threadpool that can never give up an unused thread.  In 1.5.7+,
 * the values can diverge, and if you set coreSize < maximumSize, threads can be given up (subject to the keep-alive
 * time)
 *
 * It is OK to leave maximumSize unset using any version of Hystrix.  If you do, then maximum size will default to
 * core size and you'll have a fixed-size threadpool.
 *
 * If you accidentally set maximumSize < coreSize, then maximum will be raised to coreSize
 * (this prioritizes keeping extra threads around rather than inducing threadpool rejections)
 */
public abstract class HystrixThreadPoolProperties {

    /* defaults */
    static int default_coreSize = 10;            // core size of thread pool
    static int default_maximumSize = 10;         // maximum size of thread pool
    static int default_keepAliveTimeMinutes = 1; // minutes to keep a thread alive
    static int default_maxQueueSize = -1;        // size of queue (this can't be dynamically changed so we use 'queueSizeRejectionThreshold' to artificially limit and reject)
                                                 // -1 turns it off and makes us use SynchronousQueue
    static boolean default_allow_maximum_size_to_diverge_from_core_size = false; //should the maximumSize config value get read and used in configuring the threadPool
                                                                                 //turning this on should be a conscious decision by the user, so we default it to false

    static int default_queueSizeRejectionThreshold = 5; // number of items in queue
    static int default_threadPoolRollingNumberStatisticalWindow = 10000; // milliseconds for rolling number
    static int default_threadPoolRollingNumberStatisticalWindowBuckets = 10; // number of buckets in rolling number (10 1-second buckets)

    private final HystrixProperty<Integer> corePoolSize;
    private final HystrixProperty<Integer> maximumPoolSize;
    private final HystrixProperty<Integer> keepAliveTime;
    private final HystrixProperty<Integer> maxQueueSize;
    private final HystrixProperty<Integer> queueSizeRejectionThreshold;
    private final HystrixProperty<Boolean> allowMaximumSizeToDivergeFromCoreSize;

    private final HystrixProperty<Integer> threadPoolRollingNumberStatisticalWindowInMilliseconds;
    private final HystrixProperty<Integer> threadPoolRollingNumberStatisticalWindowBuckets;
    //......
}

The default value of relevant parameter meter for hystrix thread pool is provided.

HystrixCollapserProperties

hystrix-core-1.5.12-sources.jar! /com/netflix/hystrix/HystrixCollapserProperties.java

/**
 * Properties for instances of {@link HystrixCollapser}.
 * <p>
 * Default implementation of methods uses Archaius (https://github.com/Netflix/archaius)
 */
public abstract class HystrixCollapserProperties {

    /* defaults */
    private static final Integer default_maxRequestsInBatch = Integer.MAX_VALUE;
    private static final Integer default_timerDelayInMilliseconds = 10;
    private static final Boolean default_requestCacheEnabled = true;
    /* package */ static final Integer default_metricsRollingStatisticalWindow = 10000;// default => statisticalWindow: 10000 = 10 seconds (and default of 10 buckets so each bucket is 1 second)
    private static final Integer default_metricsRollingStatisticalWindowBuckets = 10;// default => statisticalWindowBuckets: 10 = 10 buckets in a 10 second window so each bucket is 1 second
    private static final Boolean default_metricsRollingPercentileEnabled = true;
    private static final Integer default_metricsRollingPercentileWindow = 60000; // default to 1 minute for RollingPercentile
    private static final Integer default_metricsRollingPercentileWindowBuckets = 6; // default to 6 buckets (10 seconds each in 60 second window)
    private static final Integer default_metricsRollingPercentileBucketSize = 100; // default to 100 values max per bucket

    private final HystrixProperty<Integer> maxRequestsInBatch;
    private final HystrixProperty<Integer> timerDelayInMilliseconds;
    private final HystrixProperty<Boolean> requestCacheEnabled;
    private final HystrixProperty<Integer> metricsRollingStatisticalWindowInMilliseconds; // milliseconds back that will be tracked
    private final HystrixProperty<Integer> metricsRollingStatisticalWindowBuckets; // number of buckets in the statisticalWindow
    private final HystrixProperty<Boolean> metricsRollingPercentileEnabled; // Whether monitoring should be enabled
    private final HystrixProperty<Integer> metricsRollingPercentileWindowInMilliseconds; // number of milliseconds that will be tracked in RollingPercentile
    private final HystrixProperty<Integer> metricsRollingPercentileWindowBuckets; // number of buckets percentileWindow will be divided into
    private final HystrixProperty<Integer> metricsRollingPercentileBucketSize; // how many values will be stored in each percentileWindowBucket
    //......
}

Hystrix collapser related parameter meter default values are provided.

HystrixTimerThreadPoolProperties

hystrix-core-1.5.12-sources.jar! /com/netflix/hystrix/HystrixTimerThreadPoolProperties.java

/**
 * Properties for Hystrix timer thread pool.
 * <p>
 * Default implementation of methods uses Archaius (https://github.com/Netflix/archaius)
 */
public abstract class HystrixTimerThreadPoolProperties {

    private final HystrixProperty<Integer> corePoolSize;

    protected HystrixTimerThreadPoolProperties() {
        this(new Setter().withCoreSize(Runtime.getRuntime().availableProcessors()));
    }
    //......
}

HystrixtTimer ThreadPool related parameters are provided, mainly CoreBoost, default is runtime.getRuntime (). Available Processors ()

HystrixPropertiesChainedProperty

hystrix-core-1.5.12-sources.jar! /com/netflix/hystrix/strategy/properties/HystrixPropertiesChainedProperty.java

    public static abstract class ChainBuilder<T> {
        
        private ChainBuilder() {
            super();        
        }
        
        private List<HystrixDynamicProperty<T>> properties = 
                new ArrayList<HystrixDynamicProperty<T>>();
        
        
        public ChainBuilder<T> add(HystrixDynamicProperty<T> property) {
            properties.add(property);
            return this;
        }
        
        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);
            
        }
        
        protected abstract Class<T> getType();
        
    }

What build returns here is the implementation of HYSTRIXDYNAMicPropertyCHAINHYSTRIXProperty, which is specifically obtained by HystrixDynamicProperty.

HystrixDynamicProperties

hystrix-core-1.5.12-sources.jar! /com/netflix/hystrix/strategy/properties/HystrixDynamicProperties.java

/**
 * A hystrix plugin (SPI) for resolving dynamic configuration properties. This
 * SPI allows for varying configuration sources.
 * 
 * The HystrixPlugin singleton will load only one implementation of this SPI
 * throught the {@link ServiceLoader} mechanism.
 * 
 * @author agentgt
 *
 */
public interface HystrixDynamicProperties {
    
    /**
     * Requests a property that may or may not actually exist.
     * @param name property name, never <code>null</code>
     * @param fallback default value, maybe <code>null</code>
     * @return never <code>null</code>
     */
    public HystrixDynamicProperty<String> getString(String name, String fallback);
    /**
     * Requests a property that may or may not actually exist.
     * @param name property name, never <code>null</code>
     * @param fallback default value, maybe <code>null</code>
     * @return never <code>null</code>
     */
    public HystrixDynamicProperty<Integer> getInteger(String name, Integer fallback);
    /**
     * Requests a property that may or may not actually exist.
     * @param name property name, never <code>null</code>
     * @param fallback default value, maybe <code>null</code>
     * @return never <code>null</code>
     */
    public HystrixDynamicProperty<Long> getLong(String name, Long fallback);
    /**
     * Requests a property that may or may not actually exist.
     * @param name property name
     * @param fallback default value
     * @return never <code>null</code>
     */
    public HystrixDynamicProperty<Boolean> getBoolean(String name, Boolean fallback);
    
    /**
     * @ExcludeFromJavadoc
     */
    public static class Util {
        /**
         * A convenience method to get a property by type (Class).
         * @param properties never <code>null</code>
         * @param name never <code>null</code>
         * @param fallback maybe <code>null</code>
         * @param type never <code>null</code>
         * @return a dynamic property with type T.
         */
        @SuppressWarnings("unchecked")
        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();
        }
    }
    
}

This interface only regulates some methods of obtaining dynamic parameters.

HystrixPlugins.resolveDynamicProperties

hystrix-core-1.5.12-sources.jar! /com/netflix/hystrix/strategy/HystrixPlugins.java

    private static HystrixDynamicProperties resolveDynamicProperties(ClassLoader classLoader, LoggerSupplier logSupplier) {
        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;
        }
        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;
        }
        hp = HystrixArchaiusHelper.createArchaiusDynamicProperties();
        if (hp != null) {
            logSupplier.getLogger().debug("Created HystrixDynamicProperties. Using class : {}", 
                    hp.getClass().getCanonicalName());
            return hp;
        }
        hp = HystrixDynamicPropertiesSystemProperties.getInstance();
        logSupplier.getLogger().info("Using System Properties for HystrixDynamicProperties! Using class: {}", 
                hp.getClass().getCanonicalName());
        return hp;
    }

This method is used to determine which implementation class of HystrixDynamicProperties to use. The priority is as follows:

  • Hystrix.plugin.hystrixdynamicproperties.implementation specifies the implementation class
  • The implementation class of HystrixDynamicProperties found by ServiceLoader
  • Implemented using com.netflix.hy strix.strategy.properties.archaius.hy strixdynamicpropertiesesarchaius
  • Using the System Variable HystrixDynamicpropertiesysTemproperties

Summary

HystrixPropertiesStrategy provides developers with the ability to customize the configuration of each component of hystrix. For a specific configuration, if there is no configuration, the default parameter value in the code will be used. At present, the implementation of HystrixDynamicProperties found by default in the code is HYSTRIXDYNAMIC PROPERTIES SARCHAIUS.

doc