/* * Copyright 2014 Avanza Bank AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.avanza.astrix.ft.hystrix; import com.avanza.astrix.beans.config.BeanConfiguration; import com.avanza.astrix.beans.core.AstrixBeanSettings; import com.avanza.astrix.beans.core.AstrixBeanSettings.BooleanBeanSetting; import com.avanza.astrix.beans.core.AstrixBeanSettings.IntBeanSetting; import com.avanza.astrix.beans.core.AstrixBeanSettings.StringBeanSetting; import com.netflix.hystrix.HystrixCommandKey; import com.netflix.hystrix.HystrixCommandProperties; import com.netflix.hystrix.strategy.properties.HystrixProperty; final class AstrixCommandProperties extends HystrixCommandProperties { private final ExecutionIsolationStrategy isolationStrategy; private final DynamicPropertyAdapter<Integer> executionTimeoutInMilliseconds; private final HystrixProperty<Boolean> circuitBreakerEnabled; private final HystrixProperty<Integer> circuitBreakerErrorThresholdPercentage; private final HystrixProperty<Boolean> circuitBreakerForceClosed; private final HystrixProperty<Boolean> circuitBreakerForceOpen; private final HystrixProperty<Integer> circuitBreakerRequestVolumeThreshold; private final HystrixProperty<Integer> circuitBreakerSleepWindowInMilliseconds; private final HystrixProperty<Integer> executionIsolationSemaphoreMaxConcurrentRequests; private final HystrixProperty<Boolean> executionIsolationThreadInterruptOnTimeout; private final HystrixProperty<String> executionIsolationThreadPoolKeyOverride; private final HystrixProperty<Boolean> executionTimeoutEnabled; private final HystrixProperty<Boolean> fallbackEnabled; private final HystrixProperty<Integer> metricsHealthSnapshotIntervalInMilliseconds; private final HystrixProperty<Integer> metricsRollingPercentileBucketSize; private final HystrixProperty<Boolean> metricsRollingPercentileEnabled; private final HystrixProperty<Integer> metricsRollingPercentileWindowBuckets; private final HystrixProperty<Integer> metricsRollingPercentileWindowInMilliseconds; private final HystrixProperty<Integer> metricsRollingStatisticalWindowBuckets; private final HystrixProperty<Integer> metricsRollingStatisticalWindowInMilliseconds; private final HystrixProperty<Boolean> requestCacheEnabled; private final HystrixProperty<Boolean> requestLogEnabled; AstrixCommandProperties(BeanConfiguration beanConfiguration, HystrixCommandKey key, com.netflix.hystrix.HystrixCommandProperties.Setter builder) { super(key, builder); this.isolationStrategy = builder.getExecutionIsolationStrategy(); // We create all these property adaptors here as each and every one results in creation of several temporary String objects. // The alternative to this, to create the adaptors at call-time in the various methods of this class, results in large amounts // of temporary objects and thus heavy GC load in systems with many astrix calls. this.executionTimeoutInMilliseconds = new DynamicPropertyAdapter<>(beanConfiguration.get(AstrixBeanSettings.TIMEOUT)); this.circuitBreakerEnabled = new DynamicPropertyAdapter<>(beanConfiguration.get(new BooleanBeanSetting("faultTolerance.circuitBreakerEnabled", true))); this.circuitBreakerErrorThresholdPercentage = new DynamicPropertyAdapter<>(beanConfiguration.get(new IntBeanSetting("faultTolerance.circuitBreakerErrorThresholdPercentage", 50))); this.circuitBreakerForceClosed = new DynamicPropertyAdapter<>(beanConfiguration.get(new BooleanBeanSetting("faultTolerance.circuitBreakerForceClosed", false))); this.circuitBreakerForceOpen = new DynamicPropertyAdapter<>(beanConfiguration.get(new BooleanBeanSetting("faultTolerance.circuitBreakerForceOpen", false))); this.circuitBreakerRequestVolumeThreshold = new DynamicPropertyAdapter<>(beanConfiguration.get(new IntBeanSetting("faultTolerance.circuitBreakerRequestVolumeThreshold", 20))); this.circuitBreakerSleepWindowInMilliseconds = new DynamicPropertyAdapter<>(beanConfiguration.get(new IntBeanSetting("faultTolerance.circuitBreakerSleepWindowInMilliseconds", 5000))); this.executionIsolationSemaphoreMaxConcurrentRequests = new DynamicPropertyAdapter<>(beanConfiguration.get(AstrixBeanSettings.MAX_CONCURRENT_REQUESTS)); this.executionIsolationThreadInterruptOnTimeout = new DynamicPropertyAdapter<>(beanConfiguration.get(new BooleanBeanSetting("faultTolerance.executionIsolationThreadInterruptOnTimeout", true))); this.executionIsolationThreadPoolKeyOverride = new DynamicPropertyAdapter<>(beanConfiguration.get(new StringBeanSetting("faultTolerance.executionIsolationThreadPoolKeyOverride", null))); this.executionTimeoutEnabled = new DynamicPropertyAdapter<>(beanConfiguration.get(new BooleanBeanSetting("faultTolerance.executionTimeoutEnabled", true))); this.fallbackEnabled = new DynamicPropertyAdapter<>(beanConfiguration.get(new BooleanBeanSetting("faultTolerance.fallbackEnabled", true))); this.metricsHealthSnapshotIntervalInMilliseconds = new DynamicPropertyAdapter<>(beanConfiguration.get(new IntBeanSetting("faultTolerance.metricsHealthSnapshotIntervalInMilliseconds", 500))); this.metricsRollingPercentileBucketSize = new DynamicPropertyAdapter<>(beanConfiguration.get(new IntBeanSetting("faultTolerance.metricsRollingPercentileBucketSize", 100))); this.metricsRollingPercentileEnabled = new DynamicPropertyAdapter<>(beanConfiguration.get(new BooleanBeanSetting("faultTolerance.metricsRollingPercentileEnabled", true))); this.metricsRollingPercentileWindowBuckets = new DynamicPropertyAdapter<>(beanConfiguration.get(new IntBeanSetting("faultTolerance.metricsRollingPercentileWindowBuckets", 6))); this.metricsRollingPercentileWindowInMilliseconds = new DynamicPropertyAdapter<>(beanConfiguration.get(new IntBeanSetting("faultTolerance.metricsRollingPercentileWindowInMilliseconds", 60_000))); this.metricsRollingStatisticalWindowBuckets = new DynamicPropertyAdapter<>(beanConfiguration.get(new IntBeanSetting("faultTolerance.metricsRollingStatisticalWindowBuckets", 10))); this.metricsRollingStatisticalWindowInMilliseconds = new DynamicPropertyAdapter<>(beanConfiguration.get(new IntBeanSetting("faultTolerance.metricsRollingStatisticalWindowInMilliseconds", 10_000))); this.requestCacheEnabled = new DynamicPropertyAdapter<>(beanConfiguration.get(new BooleanBeanSetting("faultTolerance.requestCacheEnabled", false))); this.requestLogEnabled = new DynamicPropertyAdapter<>(beanConfiguration.get(new BooleanBeanSetting("faultTolerance.requestLogEnabled", false))); } @Override public HystrixProperty<Integer> executionTimeoutInMilliseconds() { return executionTimeoutInMilliseconds; } @Override public HystrixProperty<Boolean> circuitBreakerEnabled() { return circuitBreakerEnabled; } @Override public HystrixProperty<Integer> circuitBreakerErrorThresholdPercentage() { return circuitBreakerErrorThresholdPercentage; } @Override public HystrixProperty<Boolean> circuitBreakerForceClosed() { return circuitBreakerForceClosed; } @Override public HystrixProperty<Boolean> circuitBreakerForceOpen() { return circuitBreakerForceOpen; } @Override public HystrixProperty<Integer> circuitBreakerRequestVolumeThreshold() { return circuitBreakerRequestVolumeThreshold; } @Override public HystrixProperty<Integer> circuitBreakerSleepWindowInMilliseconds() { return circuitBreakerSleepWindowInMilliseconds; } @Override public HystrixProperty<Integer> executionIsolationSemaphoreMaxConcurrentRequests() { return executionIsolationSemaphoreMaxConcurrentRequests; } @Override public HystrixProperty<ExecutionIsolationStrategy> executionIsolationStrategy() { // Don't allow change isolation strategy at runtime if (this.isolationStrategy != null) { return HystrixProperty.Factory.asProperty(this.isolationStrategy); } return HystrixProperty.Factory.asProperty(ExecutionIsolationStrategy.THREAD); } @Override public HystrixProperty<Boolean> executionIsolationThreadInterruptOnTimeout() { return executionIsolationThreadInterruptOnTimeout; } @Override public HystrixProperty<String> executionIsolationThreadPoolKeyOverride() { return executionIsolationThreadPoolKeyOverride; } @Override @Deprecated public HystrixProperty<Integer> executionIsolationThreadTimeoutInMilliseconds() { return executionTimeoutInMilliseconds(); } @Override public HystrixProperty<Boolean> executionTimeoutEnabled() { return executionTimeoutEnabled; } @Override public HystrixProperty<Boolean> fallbackEnabled() { return fallbackEnabled; } @Override public HystrixProperty<Integer> fallbackIsolationSemaphoreMaxConcurrentRequests() { /* * Astrix does not use the fallback of HystrixCommand to do any unsafe operations, and * we always want to call the getFallback method to get proper handling of a failed * service invocation in Astrix, see HystrixCommandFacade/HystrixObservableCommandFacade. * */ return HystrixProperty.Factory.asProperty(Integer.MAX_VALUE); } @Override public HystrixProperty<Integer> metricsHealthSnapshotIntervalInMilliseconds() { return metricsHealthSnapshotIntervalInMilliseconds; } @Override public HystrixProperty<Integer> metricsRollingPercentileBucketSize() { return metricsRollingPercentileBucketSize; } @Override public HystrixProperty<Boolean> metricsRollingPercentileEnabled() { return metricsRollingPercentileEnabled; } @Deprecated @Override public HystrixProperty<Integer> metricsRollingPercentileWindow() { return metricsRollingPercentileWindowInMilliseconds(); } @Override public HystrixProperty<Integer> metricsRollingPercentileWindowBuckets() { return metricsRollingPercentileWindowBuckets; } @Override public HystrixProperty<Integer> metricsRollingPercentileWindowInMilliseconds() { return metricsRollingPercentileWindowInMilliseconds; } @Override public HystrixProperty<Integer> metricsRollingStatisticalWindowBuckets() { return metricsRollingStatisticalWindowBuckets; } @Override public HystrixProperty<Integer> metricsRollingStatisticalWindowInMilliseconds() { return metricsRollingStatisticalWindowInMilliseconds; } @Override public HystrixProperty<Boolean> requestCacheEnabled() { return requestCacheEnabled; } @Override public HystrixProperty<Boolean> requestLogEnabled() { return requestLogEnabled; } }