You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2019/06/12 07:42:20 UTC
[camel] branch master updated: CAMEL-13354: Camel Main can now
configure Hystrix EIP
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/master by this push:
new fcf913c CAMEL-13354: Camel Main can now configure Hystrix EIP
fcf913c is described below
commit fcf913c38ad0eb635629816dc577c31e5414e63b
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Jun 12 09:42:01 2019 +0200
CAMEL-13354: Camel Main can now configure Hystrix EIP
---
.../camel/main/HystrixConfigurationProperties.java | 760 +++++++++++++++++++++
.../camel/main/MainConfigurationProperties.java | 7 +
.../java/org/apache/camel/main/MainSupport.java | 23 +-
.../src/main/resources/application.properties | 3 +
4 files changed, 790 insertions(+), 3 deletions(-)
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/HystrixConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/HystrixConfigurationProperties.java
new file mode 100644
index 0000000..b81d7d1
--- /dev/null
+++ b/core/camel-main/src/main/java/org/apache/camel/main/HystrixConfigurationProperties.java
@@ -0,0 +1,760 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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 org.apache.camel.main;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Global configuration for Hystrix EIP circuit breaker.
+ */
+public class HystrixConfigurationProperties {
+
+ private final MainConfigurationProperties parent;
+
+ private String groupKey;
+ private String threadPoolKey;
+ private Boolean circuitBreakerEnabled;
+ private Integer circuitBreakerErrorThresholdPercentage;
+ private Boolean circuitBreakerForceClosed;
+ private Boolean circuitBreakerForceOpen;
+ private Integer circuitBreakerRequestVolumeThreshold;
+ private Integer circuitBreakerSleepWindowInMilliseconds;
+ private Integer executionIsolationSemaphoreMaxConcurrentRequests;
+ private String executionIsolationStrategy;
+ private Boolean executionIsolationThreadInterruptOnTimeout;
+ private Integer executionTimeoutInMilliseconds;
+ private Boolean executionTimeoutEnabled;
+ private Integer fallbackIsolationSemaphoreMaxConcurrentRequests;
+ private Boolean fallbackEnabled;
+ private Integer metricsHealthSnapshotIntervalInMilliseconds;
+ private Integer metricsRollingPercentileBucketSize;
+ private Boolean metricsRollingPercentileEnabled;
+ private Integer metricsRollingPercentileWindowInMilliseconds;
+ private Integer metricsRollingPercentileWindowBuckets;
+ private Integer metricsRollingStatisticalWindowInMilliseconds;
+ private Integer metricsRollingStatisticalWindowBuckets;
+ private Boolean requestLogEnabled;
+ // thread-pool
+ private Integer corePoolSize;
+ private Integer maximumSize;
+ private Integer keepAliveTime;
+ private Integer maxQueueSize;
+ private Integer queueSizeRejectionThreshold;
+ private Integer threadPoolRollingNumberStatisticalWindowInMilliseconds;
+ private Integer threadPoolRollingNumberStatisticalWindowBuckets;
+ private Boolean allowMaximumSizeToDivergeFromCoreSize;
+
+ public HystrixConfigurationProperties(MainConfigurationProperties parent) {
+ this.parent = parent;
+ }
+
+ public MainConfigurationProperties end() {
+ return parent;
+ }
+
+ // getter and setters
+ // --------------------------------------------------------------
+
+ public String getGroupKey() {
+ return groupKey;
+ }
+
+ /**
+ * Sets the group key to use. The default value is CamelHystrix.
+ */
+ public void setGroupKey(String groupKey) {
+ this.groupKey = groupKey;
+ }
+
+ public String getThreadPoolKey() {
+ return threadPoolKey;
+ }
+
+ /**
+ * Sets the thread pool key to use. Will by default use the same value as groupKey has been configured to use.
+ */
+ public void setThreadPoolKey(String threadPoolKey) {
+ this.threadPoolKey = threadPoolKey;
+ }
+
+ public Boolean getCircuitBreakerEnabled() {
+ return circuitBreakerEnabled;
+ }
+
+ /**
+ * Whether to use a HystrixCircuitBreaker or not. If false no circuit-breaker logic will be used and all requests permitted.
+ * <p>
+ * This is similar in effect to circuitBreakerForceClosed() except that continues tracking metrics and knowing whether it
+ * should be open/closed, this property results in not even instantiating a circuit-breaker.
+ */
+ public void setCircuitBreakerEnabled(Boolean circuitBreakerEnabled) {
+ this.circuitBreakerEnabled = circuitBreakerEnabled;
+ }
+
+ public Integer getCircuitBreakerErrorThresholdPercentage() {
+ return circuitBreakerErrorThresholdPercentage;
+ }
+
+ /**
+ * Error percentage threshold (as whole number such as 50) at which point the circuit breaker will trip open and reject requests.
+ * <p>
+ * It will stay tripped for the duration defined in circuitBreakerSleepWindowInMilliseconds;
+ * <p>
+ * The error percentage this is compared against comes from HystrixCommandMetrics.getHealthCounts().
+ */
+ public void setCircuitBreakerErrorThresholdPercentage(Integer circuitBreakerErrorThresholdPercentage) {
+ this.circuitBreakerErrorThresholdPercentage = circuitBreakerErrorThresholdPercentage;
+ }
+
+ public Boolean getCircuitBreakerForceClosed() {
+ return circuitBreakerForceClosed;
+ }
+
+ /**
+ * If true the HystrixCircuitBreaker#allowRequest() will always return true to allow requests regardless of
+ * the error percentage from HystrixCommandMetrics.getHealthCounts().
+ * <p>
+ * The circuitBreakerForceOpen() property takes precedence so if it set to true this property does nothing.
+ */
+ public void setCircuitBreakerForceClosed(Boolean circuitBreakerForceClosed) {
+ this.circuitBreakerForceClosed = circuitBreakerForceClosed;
+ }
+
+ public Boolean getCircuitBreakerForceOpen() {
+ return circuitBreakerForceOpen;
+ }
+
+ /**
+ * If true the HystrixCircuitBreaker.allowRequest() will always return false, causing the circuit to be open (tripped) and reject all requests.
+ * <p>
+ * This property takes precedence over circuitBreakerForceClosed();
+ */
+ public void setCircuitBreakerForceOpen(Boolean circuitBreakerForceOpen) {
+ this.circuitBreakerForceOpen = circuitBreakerForceOpen;
+ }
+
+ public Integer getCircuitBreakerRequestVolumeThreshold() {
+ return circuitBreakerRequestVolumeThreshold;
+ }
+
+ /**
+ * Minimum number of requests in the metricsRollingStatisticalWindowInMilliseconds() that must exist before the HystrixCircuitBreaker will trip.
+ * <p>
+ * If below this number the circuit will not trip regardless of error percentage.
+ */
+ public void setCircuitBreakerRequestVolumeThreshold(Integer circuitBreakerRequestVolumeThreshold) {
+ this.circuitBreakerRequestVolumeThreshold = circuitBreakerRequestVolumeThreshold;
+ }
+
+ public Integer getCircuitBreakerSleepWindowInMilliseconds() {
+ return circuitBreakerSleepWindowInMilliseconds;
+ }
+
+ /**
+ * The time in milliseconds after a HystrixCircuitBreaker trips open that it should wait before trying requests again.
+ */
+ public void setCircuitBreakerSleepWindowInMilliseconds(Integer circuitBreakerSleepWindowInMilliseconds) {
+ this.circuitBreakerSleepWindowInMilliseconds = circuitBreakerSleepWindowInMilliseconds;
+ }
+
+ public Integer getExecutionIsolationSemaphoreMaxConcurrentRequests() {
+ return executionIsolationSemaphoreMaxConcurrentRequests;
+ }
+
+ /**
+ * Number of concurrent requests permitted to HystrixCommand.run(). Requests beyond the concurrent limit will be rejected.
+ * <p>
+ * Applicable only when executionIsolationStrategy == SEMAPHORE.
+ */
+ public void setExecutionIsolationSemaphoreMaxConcurrentRequests(Integer executionIsolationSemaphoreMaxConcurrentRequests) {
+ this.executionIsolationSemaphoreMaxConcurrentRequests = executionIsolationSemaphoreMaxConcurrentRequests;
+ }
+
+ public String getExecutionIsolationStrategy() {
+ return executionIsolationStrategy;
+ }
+
+ /**
+ * What isolation strategy HystrixCommand.run() will be executed with.
+ * <p>
+ * If THREAD then it will be executed on a separate thread and concurrent requests limited by the number of threads in the thread-pool.
+ * <p>
+ * If SEMAPHORE then it will be executed on the calling thread and concurrent requests limited by the semaphore count.
+ */
+ public void setExecutionIsolationStrategy(String executionIsolationStrategy) {
+ this.executionIsolationStrategy = executionIsolationStrategy;
+ }
+
+ public Boolean getExecutionIsolationThreadInterruptOnTimeout() {
+ return executionIsolationThreadInterruptOnTimeout;
+ }
+
+ /**
+ * Whether the execution thread should attempt an interrupt (using {@link Future#cancel}) when a thread times out.
+ * <p>
+ * Applicable only when executionIsolationStrategy() == THREAD.
+ */
+ public void setExecutionIsolationThreadInterruptOnTimeout(Boolean executionIsolationThreadInterruptOnTimeout) {
+ this.executionIsolationThreadInterruptOnTimeout = executionIsolationThreadInterruptOnTimeout;
+ }
+
+ public Integer getExecutionTimeoutInMilliseconds() {
+ return executionTimeoutInMilliseconds;
+ }
+
+ /**
+ * Time in milliseconds at which point the command will timeout and halt execution.
+ * <p>
+ * If {@link #executionIsolationThreadInterruptOnTimeout} == true and the command is thread-isolated, the executing thread will be interrupted.
+ * If the command is semaphore-isolated and a HystrixObservableCommand, that command will get unsubscribed.
+ */
+ public void setExecutionTimeoutInMilliseconds(Integer executionTimeoutInMilliseconds) {
+ this.executionTimeoutInMilliseconds = executionTimeoutInMilliseconds;
+ }
+
+ public Boolean getExecutionTimeoutEnabled() {
+ return executionTimeoutEnabled;
+ }
+
+ /**
+ * Whether the timeout mechanism is enabled for this command
+ */
+ public void setExecutionTimeoutEnabled(Boolean executionTimeoutEnabled) {
+ this.executionTimeoutEnabled = executionTimeoutEnabled;
+ }
+
+ public Integer getFallbackIsolationSemaphoreMaxConcurrentRequests() {
+ return fallbackIsolationSemaphoreMaxConcurrentRequests;
+ }
+
+ /**
+ * Number of concurrent requests permitted to HystrixCommand.getFallback().
+ * Requests beyond the concurrent limit will fail-fast and not attempt retrieving a fallback.
+ */
+ public void setFallbackIsolationSemaphoreMaxConcurrentRequests(Integer fallbackIsolationSemaphoreMaxConcurrentRequests) {
+ this.fallbackIsolationSemaphoreMaxConcurrentRequests = fallbackIsolationSemaphoreMaxConcurrentRequests;
+ }
+
+ public Boolean getFallbackEnabled() {
+ return fallbackEnabled;
+ }
+
+ /**
+ * Whether HystrixCommand.getFallback() should be attempted when failure occurs.
+ */
+ public void setFallbackEnabled(Boolean fallbackEnabled) {
+ this.fallbackEnabled = fallbackEnabled;
+ }
+
+ public Integer getMetricsHealthSnapshotIntervalInMilliseconds() {
+ return metricsHealthSnapshotIntervalInMilliseconds;
+ }
+
+ /**
+ * Time in milliseconds to wait between allowing health snapshots to be taken that calculate success and error
+ * percentages and affect HystrixCircuitBreaker.isOpen() status.
+ * <p>
+ * On high-volume circuits the continual calculation of error percentage can become CPU intensive thus this controls how often it is calculated.
+ */
+ public void setMetricsHealthSnapshotIntervalInMilliseconds(Integer metricsHealthSnapshotIntervalInMilliseconds) {
+ this.metricsHealthSnapshotIntervalInMilliseconds = metricsHealthSnapshotIntervalInMilliseconds;
+ }
+
+ public Integer getMetricsRollingPercentileBucketSize() {
+ return metricsRollingPercentileBucketSize;
+ }
+
+ /**
+ * Maximum number of values stored in each bucket of the rolling percentile.
+ * This is passed into HystrixRollingPercentile inside HystrixCommandMetrics.
+ */
+ public void setMetricsRollingPercentileBucketSize(Integer metricsRollingPercentileBucketSize) {
+ this.metricsRollingPercentileBucketSize = metricsRollingPercentileBucketSize;
+ }
+
+ public Boolean getMetricsRollingPercentileEnabled() {
+ return metricsRollingPercentileEnabled;
+ }
+
+ /**
+ * Whether percentile metrics should be captured using HystrixRollingPercentile inside HystrixCommandMetrics.
+ */
+ public void setMetricsRollingPercentileEnabled(Boolean metricsRollingPercentileEnabled) {
+ this.metricsRollingPercentileEnabled = metricsRollingPercentileEnabled;
+ }
+
+ public Integer getMetricsRollingPercentileWindowInMilliseconds() {
+ return metricsRollingPercentileWindowInMilliseconds;
+ }
+
+ /**
+ * Duration of percentile rolling window in milliseconds.
+ * This is passed into HystrixRollingPercentile inside HystrixCommandMetrics.
+ */
+ public void setMetricsRollingPercentileWindowInMilliseconds(Integer metricsRollingPercentileWindowInMilliseconds) {
+ this.metricsRollingPercentileWindowInMilliseconds = metricsRollingPercentileWindowInMilliseconds;
+ }
+
+ public Integer getMetricsRollingPercentileWindowBuckets() {
+ return metricsRollingPercentileWindowBuckets;
+ }
+
+ /**
+ * Number of buckets the rolling percentile window is broken into.
+ * This is passed into HystrixRollingPercentile inside HystrixCommandMetrics.
+ */
+ public void setMetricsRollingPercentileWindowBuckets(Integer metricsRollingPercentileWindowBuckets) {
+ this.metricsRollingPercentileWindowBuckets = metricsRollingPercentileWindowBuckets;
+ }
+
+ public Integer getMetricsRollingStatisticalWindowInMilliseconds() {
+ return metricsRollingStatisticalWindowInMilliseconds;
+ }
+
+ /**
+ * This property sets the duration of the statistical rolling window, in milliseconds. This is how long metrics are kept for the thread pool.
+ *
+ * The window is divided into buckets and “rolls” by those increments.
+ */
+ public void setMetricsRollingStatisticalWindowInMilliseconds(Integer metricsRollingStatisticalWindowInMilliseconds) {
+ this.metricsRollingStatisticalWindowInMilliseconds = metricsRollingStatisticalWindowInMilliseconds;
+ }
+
+ public Integer getMetricsRollingStatisticalWindowBuckets() {
+ return metricsRollingStatisticalWindowBuckets;
+ }
+
+ /**
+ * Number of buckets the rolling statistical window is broken into.
+ * This is passed into HystrixRollingNumber inside HystrixCommandMetrics.
+ */
+ public void setMetricsRollingStatisticalWindowBuckets(Integer metricsRollingStatisticalWindowBuckets) {
+ this.metricsRollingStatisticalWindowBuckets = metricsRollingStatisticalWindowBuckets;
+ }
+
+ public Boolean getRequestLogEnabled() {
+ return requestLogEnabled;
+ }
+
+ /**
+ * Whether HystrixCommand execution and events should be logged to HystrixRequestLog.
+ */
+ public void setRequestLogEnabled(Boolean requestLogEnabled) {
+ this.requestLogEnabled = requestLogEnabled;
+ }
+
+ public Integer getCorePoolSize() {
+ return corePoolSize;
+ }
+
+ /**
+ * Core thread-pool size that gets passed to {@link java.util.concurrent.ThreadPoolExecutor#setCorePoolSize(int)}
+ */
+ public void setCorePoolSize(Integer corePoolSize) {
+ this.corePoolSize = corePoolSize;
+ }
+
+ public Integer getMaximumSize() {
+ return maximumSize;
+ }
+
+ /**
+ * Maximum thread-pool size that gets passed to {@link ThreadPoolExecutor#setMaximumPoolSize(int)}.
+ * This is the maximum amount of concurrency that can be supported without starting to reject HystrixCommands.
+ * Please note that this setting only takes effect if you also set allowMaximumSizeToDivergeFromCoreSize
+ */
+ public void setMaximumSize(Integer maximumSize) {
+ this.maximumSize = maximumSize;
+ }
+
+ public Integer getKeepAliveTime() {
+ return keepAliveTime;
+ }
+
+ /**
+ * Keep-alive time in minutes that gets passed to {@link ThreadPoolExecutor#setKeepAliveTime(long, TimeUnit)}
+ */
+ public void setKeepAliveTime(Integer keepAliveTime) {
+ this.keepAliveTime = keepAliveTime;
+ }
+
+ public Integer getMaxQueueSize() {
+ return maxQueueSize;
+ }
+
+ /**
+ * Max queue size that gets passed to {@link BlockingQueue} in HystrixConcurrencyStrategy.getBlockingQueue(int)
+ *
+ * This should only affect the instantiation of a threadpool - it is not eliglible to change a queue size on the fly.
+ * For that, use queueSizeRejectionThreshold().
+ */
+ public void setMaxQueueSize(Integer maxQueueSize) {
+ this.maxQueueSize = maxQueueSize;
+ }
+
+ public Integer getQueueSizeRejectionThreshold() {
+ return queueSizeRejectionThreshold;
+ }
+
+ /**
+ * Queue size rejection threshold is an artificial "max" size at which rejections will occur even
+ * if {@link #maxQueueSize} has not been reached. This is done because the {@link #maxQueueSize}
+ * of a {@link BlockingQueue} can not be dynamically changed and we want to support dynamically
+ * changing the queue size that affects rejections.
+ * <p>
+ * This is used by HystrixCommand when queuing a thread for execution.
+ */
+ public void setQueueSizeRejectionThreshold(Integer queueSizeRejectionThreshold) {
+ this.queueSizeRejectionThreshold = queueSizeRejectionThreshold;
+ }
+
+ public Integer getThreadPoolRollingNumberStatisticalWindowInMilliseconds() {
+ return threadPoolRollingNumberStatisticalWindowInMilliseconds;
+ }
+
+ /**
+ * Duration of statistical rolling window in milliseconds.
+ * This is passed into HystrixRollingNumber inside each HystrixThreadPoolMetrics instance.
+ */
+ public void setThreadPoolRollingNumberStatisticalWindowInMilliseconds(Integer threadPoolRollingNumberStatisticalWindowInMilliseconds) {
+ this.threadPoolRollingNumberStatisticalWindowInMilliseconds = threadPoolRollingNumberStatisticalWindowInMilliseconds;
+ }
+
+ public Integer getThreadPoolRollingNumberStatisticalWindowBuckets() {
+ return threadPoolRollingNumberStatisticalWindowBuckets;
+ }
+
+ /**
+ * Number of buckets the rolling statistical window is broken into.
+ * This is passed into HystrixRollingNumber inside each HystrixThreadPoolMetrics instance.
+ */
+ public void setThreadPoolRollingNumberStatisticalWindowBuckets(Integer threadPoolRollingNumberStatisticalWindowBuckets) {
+ this.threadPoolRollingNumberStatisticalWindowBuckets = threadPoolRollingNumberStatisticalWindowBuckets;
+ }
+
+ public Boolean getAllowMaximumSizeToDivergeFromCoreSize() {
+ return allowMaximumSizeToDivergeFromCoreSize;
+ }
+
+ /**
+ * Allows the configuration for maximumSize to take effect. That value can then be equal to, or higher, than coreSize
+ */
+ public void setAllowMaximumSizeToDivergeFromCoreSize(Boolean allowMaximumSizeToDivergeFromCoreSize) {
+ this.allowMaximumSizeToDivergeFromCoreSize = allowMaximumSizeToDivergeFromCoreSize;
+ }
+
+ // fluent builders
+ // --------------------------------------------------------------
+
+ /**
+ * Sets the group key to use. The default value is CamelHystrix.
+ */
+ public HystrixConfigurationProperties withGroupKey(String groupKey) {
+ this.groupKey = groupKey;
+ return this;
+ }
+
+ /**
+ * Sets the thread pool key to use. Will by default use the same value as groupKey has been configured to use.
+ */
+ public HystrixConfigurationProperties withThreadPoolKey(String threadPoolKey) {
+ this.threadPoolKey = threadPoolKey;
+ return this;
+ }
+
+ /**
+ * Whether to use a HystrixCircuitBreaker or not. If false no circuit-breaker logic will be used and all requests permitted.
+ * <p>
+ * This is similar in effect to circuitBreakerForceClosed() except that continues tracking metrics and knowing whether it
+ * should be open/closed, this property results in not even instantiating a circuit-breaker.
+ */
+ public HystrixConfigurationProperties withCircuitBreakerEnabled(Boolean circuitBreakerEnabled) {
+ this.circuitBreakerEnabled = circuitBreakerEnabled;
+ return this;
+ }
+
+ /**
+ * Error percentage threshold (as whole number such as 50) at which point the circuit breaker will trip open and reject requests.
+ * <p>
+ * It will stay tripped for the duration defined in circuitBreakerSleepWindowInMilliseconds;
+ * <p>
+ * The error percentage this is compared against comes from HystrixCommandMetrics.getHealthCounts().
+ */
+ public HystrixConfigurationProperties withCircuitBreakerErrorThresholdPercentage(Integer circuitBreakerErrorThresholdPercentage) {
+ this.circuitBreakerErrorThresholdPercentage = circuitBreakerErrorThresholdPercentage;
+ return this;
+ }
+
+ /**
+ * If true the HystrixCircuitBreaker#allowRequest() will always return true to allow requests regardless of
+ * the error percentage from HystrixCommandMetrics.getHealthCounts().
+ * <p>
+ * The circuitBreakerForceOpen() property takes precedence so if it set to true this property does nothing.
+ */
+ public HystrixConfigurationProperties withCircuitBreakerForceClosed(Boolean circuitBreakerForceClosed) {
+ this.circuitBreakerForceClosed = circuitBreakerForceClosed;
+ return this;
+ }
+
+ /**
+ * If true the HystrixCircuitBreaker.allowRequest() will always return false, causing the circuit to be open (tripped) and reject all requests.
+ * <p>
+ * This property takes precedence over circuitBreakerForceClosed();
+ */
+ public HystrixConfigurationProperties withCircuitBreakerForceOpen(Boolean circuitBreakerForceOpen) {
+ this.circuitBreakerForceOpen = circuitBreakerForceOpen;
+ return this;
+ }
+
+ /**
+ * Minimum number of requests in the metricsRollingStatisticalWindowInMilliseconds() that must exist before the HystrixCircuitBreaker will trip.
+ * <p>
+ * If below this number the circuit will not trip regardless of error percentage.
+ */
+ public HystrixConfigurationProperties withCircuitBreakerRequestVolumeThreshold(Integer circuitBreakerRequestVolumeThreshold) {
+ this.circuitBreakerRequestVolumeThreshold = circuitBreakerRequestVolumeThreshold;
+ return this;
+ }
+
+ /**
+ * The time in milliseconds after a HystrixCircuitBreaker trips open that it should wait before trying requests again.
+ */
+ public HystrixConfigurationProperties withCircuitBreakerSleepWindowInMilliseconds(Integer circuitBreakerSleepWindowInMilliseconds) {
+ this.circuitBreakerSleepWindowInMilliseconds = circuitBreakerSleepWindowInMilliseconds;
+ return this;
+ }
+
+ /**
+ * Number of concurrent requests permitted to HystrixCommand.run(). Requests beyond the concurrent limit will be rejected.
+ * <p>
+ * Applicable only when executionIsolationStrategy == SEMAPHORE.
+ */
+ public HystrixConfigurationProperties withExecutionIsolationSemaphoreMaxConcurrentRequests(Integer executionIsolationSemaphoreMaxConcurrentRequests) {
+ this.executionIsolationSemaphoreMaxConcurrentRequests = executionIsolationSemaphoreMaxConcurrentRequests;
+ return this;
+ }
+
+ /**
+ * What isolation strategy HystrixCommand.run() will be executed with.
+ * <p>
+ * If THREAD then it will be executed on a separate thread and concurrent requests limited by the number of threads in the thread-pool.
+ * <p>
+ * If SEMAPHORE then it will be executed on the calling thread and concurrent requests limited by the semaphore count.
+ */
+ public HystrixConfigurationProperties withExecutionIsolationStrategy(String executionIsolationStrategy) {
+ this.executionIsolationStrategy = executionIsolationStrategy;
+ return this;
+ }
+
+ /**
+ * Whether the execution thread should attempt an interrupt (using {@link Future#cancel}) when a thread times out.
+ * <p>
+ * Applicable only when executionIsolationStrategy() == THREAD.
+ */
+ public HystrixConfigurationProperties withExecutionIsolationThreadInterruptOnTimeout(Boolean executionIsolationThreadInterruptOnTimeout) {
+ this.executionIsolationThreadInterruptOnTimeout = executionIsolationThreadInterruptOnTimeout;
+ return this;
+ }
+
+ /**
+ * Time in milliseconds at which point the command will timeout and halt execution.
+ * <p>
+ * If {@link #executionIsolationThreadInterruptOnTimeout} == true and the command is thread-isolated, the executing thread will be interrupted.
+ * If the command is semaphore-isolated and a HystrixObservableCommand, that command will get unsubscribed.
+ */
+ public HystrixConfigurationProperties withExecutionTimeoutInMilliseconds(Integer executionTimeoutInMilliseconds) {
+ this.executionTimeoutInMilliseconds = executionTimeoutInMilliseconds;
+ return this;
+ }
+
+ /**
+ * Whether the timeout mechanism is enabled for this command
+ */
+ public HystrixConfigurationProperties withExecutionTimeoutEnabled(Boolean executionTimeoutEnabled) {
+ this.executionTimeoutEnabled = executionTimeoutEnabled;
+ return this;
+ }
+
+ /**
+ * Number of concurrent requests permitted to HystrixCommand.getFallback().
+ * Requests beyond the concurrent limit will fail-fast and not attempt retrieving a fallback.
+ */
+ public HystrixConfigurationProperties withFallbackIsolationSemaphoreMaxConcurrentRequests(Integer fallbackIsolationSemaphoreMaxConcurrentRequests) {
+ this.fallbackIsolationSemaphoreMaxConcurrentRequests = fallbackIsolationSemaphoreMaxConcurrentRequests;
+ return this;
+ }
+
+ /**
+ * Whether HystrixCommand.getFallback() should be attempted when failure occurs.
+ */
+ public HystrixConfigurationProperties withFallbackEnabled(Boolean fallbackEnabled) {
+ this.fallbackEnabled = fallbackEnabled;
+ return this;
+ }
+
+ /**
+ * Time in milliseconds to wait between allowing health snapshots to be taken that calculate success and error
+ * percentages and affect HystrixCircuitBreaker.isOpen() status.
+ * <p>
+ * On high-volume circuits the continual calculation of error percentage can become CPU intensive thus this controls how often it is calculated.
+ */
+ public HystrixConfigurationProperties withMetricsHealthSnapshotIntervalInMilliseconds(Integer metricsHealthSnapshotIntervalInMilliseconds) {
+ this.metricsHealthSnapshotIntervalInMilliseconds = metricsHealthSnapshotIntervalInMilliseconds;
+ return this;
+ }
+
+ /**
+ * Maximum number of values stored in each bucket of the rolling percentile.
+ * This is passed into HystrixRollingPercentile inside HystrixCommandMetrics.
+ */
+ public HystrixConfigurationProperties withMetricsRollingPercentileBucketSize(Integer metricsRollingPercentileBucketSize) {
+ this.metricsRollingPercentileBucketSize = metricsRollingPercentileBucketSize;
+ return this;
+ }
+
+ /**
+ * Whether percentile metrics should be captured using HystrixRollingPercentile inside HystrixCommandMetrics.
+ */
+ public HystrixConfigurationProperties withMetricsRollingPercentileEnabled(Boolean metricsRollingPercentileEnabled) {
+ this.metricsRollingPercentileEnabled = metricsRollingPercentileEnabled;
+ return this;
+ }
+
+ /**
+ * Duration of percentile rolling window in milliseconds.
+ * This is passed into HystrixRollingPercentile inside HystrixCommandMetrics.
+ */
+ public HystrixConfigurationProperties withMetricsRollingPercentileWindowInMilliseconds(Integer metricsRollingPercentileWindowInMilliseconds) {
+ this.metricsRollingPercentileWindowInMilliseconds = metricsRollingPercentileWindowInMilliseconds;
+ return this;
+ }
+
+ /**
+ * Number of buckets the rolling percentile window is broken into.
+ * This is passed into HystrixRollingPercentile inside HystrixCommandMetrics.
+ */
+ public HystrixConfigurationProperties withMetricsRollingPercentileWindowBuckets(Integer metricsRollingPercentileWindowBuckets) {
+ this.metricsRollingPercentileWindowBuckets = metricsRollingPercentileWindowBuckets;
+ return this;
+ }
+
+ /**
+ * This property sets the duration of the statistical rolling window, in milliseconds. This is how long metrics are kept for the thread pool.
+ *
+ * The window is divided into buckets and “rolls” by those increments.
+ */
+ public HystrixConfigurationProperties withMetricsRollingStatisticalWindowInMilliseconds(Integer metricsRollingStatisticalWindowInMilliseconds) {
+ this.metricsRollingStatisticalWindowInMilliseconds = metricsRollingStatisticalWindowInMilliseconds;
+ return this;
+ }
+
+ /**
+ * Number of buckets the rolling statistical window is broken into.
+ * This is passed into HystrixRollingNumber inside HystrixCommandMetrics.
+ */
+ public HystrixConfigurationProperties withMetricsRollingStatisticalWindowBuckets(Integer metricsRollingStatisticalWindowBuckets) {
+ this.metricsRollingStatisticalWindowBuckets = metricsRollingStatisticalWindowBuckets;
+ return this;
+ }
+
+ /**
+ * Whether HystrixCommand execution and events should be logged to HystrixRequestLog.
+ */
+ public HystrixConfigurationProperties withRequestLogEnabled(Boolean requestLogEnabled) {
+ this.requestLogEnabled = requestLogEnabled;
+ return this;
+ }
+
+ /**
+ * Core thread-pool size that gets passed to {@link java.util.concurrent.ThreadPoolExecutor#setCorePoolSize(int)}
+ */
+ public HystrixConfigurationProperties withCorePoolSize(Integer corePoolSize) {
+ this.corePoolSize = corePoolSize;
+ return this;
+ }
+
+ /**
+ * Maximum thread-pool size that gets passed to {@link ThreadPoolExecutor#setMaximumPoolSize(int)}.
+ * This is the maximum amount of concurrency that can be supported without starting to reject HystrixCommands.
+ * Please note that this setting only takes effect if you also set allowMaximumSizeToDivergeFromCoreSize
+ */
+ public HystrixConfigurationProperties withMaximumSize(Integer maximumSize) {
+ this.maximumSize = maximumSize;
+ return this;
+ }
+
+ /**
+ * Keep-alive time in minutes that gets passed to {@link ThreadPoolExecutor#setKeepAliveTime(long, TimeUnit)}
+ */
+ public HystrixConfigurationProperties withKeepAliveTime(Integer keepAliveTime) {
+ this.keepAliveTime = keepAliveTime;
+ return this;
+ }
+
+ /**
+ * Max queue size that gets passed to {@link BlockingQueue} in HystrixConcurrencyStrategy.getBlockingQueue(int)
+ *
+ * This should only affect the instantiation of a threadpool - it is not eliglible to change a queue size on the fly.
+ * For that, use queueSizeRejectionThreshold().
+ */
+ public HystrixConfigurationProperties withMaxQueueSize(Integer maxQueueSize) {
+ this.maxQueueSize = maxQueueSize;
+ return this;
+ }
+
+ /**
+ * Queue size rejection threshold is an artificial "max" size at which rejections will occur even
+ * if {@link #maxQueueSize} has not been reached. This is done because the {@link #maxQueueSize}
+ * of a {@link BlockingQueue} can not be dynamically changed and we want to support dynamically
+ * changing the queue size that affects rejections.
+ * <p>
+ * This is used by HystrixCommand when queuing a thread for execution.
+ */
+ public HystrixConfigurationProperties withQueueSizeRejectionThreshold(Integer queueSizeRejectionThreshold) {
+ this.queueSizeRejectionThreshold = queueSizeRejectionThreshold;
+ return this;
+ }
+
+ /**
+ * Duration of statistical rolling window in milliseconds.
+ * This is passed into HystrixRollingNumber inside each HystrixThreadPoolMetrics instance.
+ */
+ public HystrixConfigurationProperties withThreadPoolRollingNumberStatisticalWindowInMilliseconds(Integer threadPoolRollingNumberStatisticalWindowInMilliseconds) {
+ this.threadPoolRollingNumberStatisticalWindowInMilliseconds = threadPoolRollingNumberStatisticalWindowInMilliseconds;
+ return this;
+ }
+
+ /**
+ * Number of buckets the rolling statistical window is broken into.
+ * This is passed into HystrixRollingNumber inside each HystrixThreadPoolMetrics instance.
+ */
+ public HystrixConfigurationProperties withThreadPoolRollingNumberStatisticalWindowBuckets(Integer threadPoolRollingNumberStatisticalWindowBuckets) {
+ this.threadPoolRollingNumberStatisticalWindowBuckets = threadPoolRollingNumberStatisticalWindowBuckets;
+ return this;
+ }
+
+ /**
+ * Allows the configuration for maximumSize to take effect. That value can then be equal to, or higher, than coreSize
+ */
+ public HystrixConfigurationProperties withAllowMaximumSizeToDivergeFromCoreSize(Boolean allowMaximumSizeToDivergeFromCoreSize) {
+ this.allowMaximumSizeToDivergeFromCoreSize = allowMaximumSizeToDivergeFromCoreSize;
+ return this;
+ }
+}
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
index c867455..eb1d255 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainConfigurationProperties.java
@@ -28,6 +28,9 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties<
private int durationHitExitCode;
private boolean hangupInterceptorEnabled = true;
+ // extended configuration
+ private final HystrixConfigurationProperties hystrixConfigurationProperties = new HystrixConfigurationProperties(this);
+
// getter and setters
// --------------------------------------------------------------
@@ -198,4 +201,8 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties<
return this;
}
+ public HystrixConfigurationProperties hystrix() {
+ return hystrixConfigurationProperties;
+ }
+
}
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
index d4ad59a..d8e1e8a 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/MainSupport.java
@@ -37,7 +37,9 @@ import org.apache.camel.Component;
import org.apache.camel.ExtendedCamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.HystrixConfigurationDefinition;
import org.apache.camel.model.Model;
+import org.apache.camel.model.ModelCamelContext;
import org.apache.camel.model.RouteDefinition;
import org.apache.camel.spi.CamelBeanPostProcessor;
import org.apache.camel.spi.DataFormat;
@@ -796,18 +798,34 @@ public abstract class MainSupport extends ServiceSupport {
// now configure context with additional properties
Properties prop = camelContext.getPropertiesComponent().loadProperties();
Map<String, Object> properties = new LinkedHashMap<>();
+ Map<String, Object> hystrixProperties = new LinkedHashMap<>();
for (String key : prop.stringPropertyNames()) {
if (key.startsWith("camel.context.")) {
// grab the value
String value = prop.getProperty(key);
String option = key.substring(14);
properties.put(option, value);
+ } else if (key.startsWith("camel.hystrix.")) {
+ // grab the value
+ String value = prop.getProperty(key);
+ String option = key.substring(14);
+ hystrixProperties.put(option, value);
}
}
if (!properties.isEmpty()) {
LOG.info("Auto configuring CamelContext from loaded properties: {}", properties.size());
+ setCamelProperties(camelContext, camelContext, properties, true);
+ }
+ if (!hystrixProperties.isEmpty()) {
+ LOG.info("Auto configuring Hystrix EIP from loaded properties: {}", hystrixProperties.size());
+ ModelCamelContext model = camelContext.adapt(ModelCamelContext.class);
+ HystrixConfigurationDefinition hystrix = model.getHystrixConfiguration(null);
+ if (hystrix == null) {
+ hystrix = new HystrixConfigurationDefinition();
+ model.setHystrixConfiguration(hystrix);
+ }
+ setCamelProperties(camelContext, hystrix, hystrixProperties, true);
}
- setCamelProperties(camelContext, camelContext, properties, true);
}
protected void autoConfigurationPropertiesComponent(CamelContext camelContext) throws Exception {
@@ -857,9 +875,8 @@ public abstract class MainSupport extends ServiceSupport {
if (!properties.isEmpty()) {
LOG.info("Auto configuring main from loaded properties: {}", properties.size());
+ setCamelProperties(camelContext, config, properties, true);
}
-
- setCamelProperties(camelContext, config, properties, true);
}
protected void autoConfigurationFromProperties(CamelContext camelContext) throws Exception {
diff --git a/examples/camel-example-main/src/main/resources/application.properties b/examples/camel-example-main/src/main/resources/application.properties
index 8bb5863..0c96fed 100644
--- a/examples/camel-example-main/src/main/resources/application.properties
+++ b/examples/camel-example-main/src/main/resources/application.properties
@@ -30,6 +30,9 @@ camel.main.file-configurations=src/main/data/*.properties
# here we can configure the options on the component level (and we can use dash-naming-style)
camel.component.quartz2.start-delayed-seconds = 3
+# to configure Hystrix EIP (global and you need to add camel-hystrix to the classpath)
+### camel.hystrix.group-key=myGroup
+### camel.hystrix.execution-timeout-in-milliseconds=5000
# you can configure whether OS environment should override (=2 which is default) or as fallback (=1)
### camel.component.properties.environment-variable-mode=1