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/11/18 09:00:49 UTC

[camel] 07/23: CAMEL-13691: camel-resilience4j - WIP

This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch CAMEL-13691
in repository https://gitbox.apache.org/repos/asf/camel.git

commit da3bf41f168026dd69b03ff0e3f911d630a1d36b
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Sun Nov 17 09:04:50 2019 +0100

    CAMEL-13691: camel-resilience4j - WIP
---
 .../component/resilience4j/ResilienceReifier.java  |   3 +
 .../org/apache/camel/main/BaseMainSupport.java     |   2 +-
 .../camel/main/MainConfigurationProperties.java    |   8 +
 .../main/Resilience4jConfigurationProperties.java  | 390 +++++++++++++++++++++
 4 files changed, 402 insertions(+), 1 deletion(-)

diff --git a/components/camel-resilience4j/src/main/java/org/apache/camel/component/resilience4j/ResilienceReifier.java b/components/camel-resilience4j/src/main/java/org/apache/camel/component/resilience4j/ResilienceReifier.java
index 06399cd..912fb3e 100644
--- a/components/camel-resilience4j/src/main/java/org/apache/camel/component/resilience4j/ResilienceReifier.java
+++ b/components/camel-resilience4j/src/main/java/org/apache/camel/component/resilience4j/ResilienceReifier.java
@@ -45,6 +45,9 @@ public class ResilienceReifier extends ProcessorReifier<CircuitBreakerDefinition
     // TODO: metrics with state of CB
     // TODO: expose metrics as JMX on processor
     // TODO: Timeout
+    // TODO: thread pool bulkhead
+    // TODO: spring-boot allow to configure via resilience4j-spring-boot
+    // TODO: example
 
     public ResilienceReifier(CircuitBreakerDefinition definition) {
         super(definition);
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
index 542ed8c..a87c01b 100644
--- a/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
+++ b/core/camel-main/src/main/java/org/apache/camel/main/BaseMainSupport.java
@@ -642,7 +642,7 @@ public abstract class BaseMainSupport extends ServiceSupport {
         // lookup and configure SPI beans
         DefaultConfigurationConfigurer.afterPropertiesSet(camelContext);
 
-        // now configure context/hystrix/rest with additional properties
+        // now configure context/hystrix/resilience4j/rest with additional properties
         Properties prop = camelContext.getPropertiesComponent().loadProperties(name -> name.startsWith("camel."));
 
         // load properties from ENV (override existing)
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 433b18d..c5eca6d 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
@@ -35,6 +35,7 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties<
 
     // extended configuration
     private final HystrixConfigurationProperties hystrixConfigurationProperties = new HystrixConfigurationProperties(this);
+    private final Resilience4jConfigurationProperties resilience4jConfigurationProperties = new Resilience4jConfigurationProperties(this);
     private final RestConfigurationProperties restConfigurationProperties = new RestConfigurationProperties(this);
 
     // extended
@@ -48,6 +49,13 @@ public class MainConfigurationProperties extends DefaultConfigurationProperties<
     }
 
     /**
+     * To configure Circuit Breaker EIP with Resilience4j
+     */
+    public Resilience4jConfigurationProperties resilience4j() {
+        return resilience4jConfigurationProperties;
+    }
+
+    /**
      * To configure Rest DSL
      */
     public RestConfigurationProperties rest() {
diff --git a/core/camel-main/src/main/java/org/apache/camel/main/Resilience4jConfigurationProperties.java b/core/camel-main/src/main/java/org/apache/camel/main/Resilience4jConfigurationProperties.java
new file mode 100644
index 0000000..db9c7b8
--- /dev/null
+++ b/core/camel-main/src/main/java/org/apache/camel/main/Resilience4jConfigurationProperties.java
@@ -0,0 +1,390 @@
+/*
+ * 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
+ *
+ *      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 org.apache.camel.main;
+
+/**
+ * Global configuration for Resilience EIP circuit breaker.
+ */
+public class Resilience4jConfigurationProperties {
+
+    private final MainConfigurationProperties parent;
+
+    private String configRef;
+    private Float failureRateThreshold;
+    private Integer permittedNumberOfCallsInHalfOpenState;
+    private Integer slidingWindowSize;
+    private String slidingWindowType;
+    private Integer minimumNumberOfCalls;
+    private Boolean writableStackTraceEnabled;
+    private Integer waitDurationInOpenState;
+    private Boolean automaticTransitionFromOpenToHalfOpenEnabled;
+    private Float slowCallRateThreshold;
+    private Integer slowCallDurationThreshold;
+    private Boolean bulkheadEnabled;
+    private Integer bulkheadMaxConcurrentCalls;
+    private Integer bulkheadMaxWaitDuration;
+
+    public Resilience4jConfigurationProperties(MainConfigurationProperties parent) {
+        this.parent = parent;
+    }
+
+    public MainConfigurationProperties end() {
+        return parent;
+    }
+
+    // getter and setters
+    // --------------------------------------------------------------
+
+    public String getConfigRef() {
+        return configRef;
+    }
+
+    /**
+     * Refers to an existing io.github.resilience4j.circuitbreaker.CircuitBreakerConfig instance
+     * to lookup and use from the registry.
+     */
+    public void setConfigRef(String configRef) {
+        this.configRef = configRef;
+    }
+
+    public Float getFailureRateThreshold() {
+        return failureRateThreshold;
+    }
+
+    /**
+     * Configures the failure rate threshold in percentage.
+     * If the failure rate is equal or greater than the threshold the CircuitBreaker transitions to open and starts short-circuiting calls.
+     * <p>
+     * The threshold must be greater than 0 and not greater than 100. Default value is 50 percentage.
+     */
+    public void setFailureRateThreshold(Float failureRateThreshold) {
+        this.failureRateThreshold = failureRateThreshold;
+    }
+
+    public Integer getPermittedNumberOfCallsInHalfOpenState() {
+        return permittedNumberOfCallsInHalfOpenState;
+    }
+
+    /**
+     * Configures the number of permitted calls when the CircuitBreaker is half open.
+     * <p>
+     * The size must be greater than 0. Default size is 10.
+     */
+    public void setPermittedNumberOfCallsInHalfOpenState(Integer permittedNumberOfCallsInHalfOpenState) {
+        this.permittedNumberOfCallsInHalfOpenState = permittedNumberOfCallsInHalfOpenState;
+    }
+
+    public Integer getSlidingWindowSize() {
+        return slidingWindowSize;
+    }
+
+    /**
+     * Configures the size of the sliding window which is used to record the outcome of calls when the CircuitBreaker is closed.
+     * {@code slidingWindowSize} configures the size of the sliding window. Sliding window can either be count-based or time-based.
+     *
+     * If {@code slidingWindowType} is COUNT_BASED, the last {@code slidingWindowSize} calls are recorded and aggregated.
+     * If {@code slidingWindowType} is TIME_BASED, the calls of the last {@code slidingWindowSize} seconds are recorded and aggregated.
+     * <p>
+     * The {@code slidingWindowSize} must be greater than 0.
+     * The {@code minimumNumberOfCalls} must be greater than 0.
+     * If the slidingWindowType is COUNT_BASED, the {@code minimumNumberOfCalls} cannot be greater than {@code slidingWindowSize}.
+     * If the slidingWindowType is TIME_BASED, you can pick whatever you want.
+     *
+     * Default slidingWindowSize is 100.
+     */
+    public void setSlidingWindowSize(Integer slidingWindowSize) {
+        this.slidingWindowSize = slidingWindowSize;
+    }
+
+    public String getSlidingWindowType() {
+        return slidingWindowType;
+    }
+
+    /**
+     * Configures the type of the sliding window which is used to record the outcome of calls when the CircuitBreaker is closed.
+     * Sliding window can either be count-based or time-based.
+     *
+     * If {@code slidingWindowType} is COUNT_BASED, the last {@code slidingWindowSize} calls are recorded and aggregated.
+     * If {@code slidingWindowType} is TIME_BASED, the calls of the last {@code slidingWindowSize} seconds are recorded and aggregated.
+     *
+     * Default slidingWindowType is COUNT_BASED.
+     */
+    public void setSlidingWindowType(String slidingWindowType) {
+        this.slidingWindowType = slidingWindowType;
+    }
+
+    public Integer getMinimumNumberOfCalls() {
+        return minimumNumberOfCalls;
+    }
+
+    /**
+     * Configures configures the minimum number of calls which are required (per sliding window period) before the CircuitBreaker can calculate the error rate.
+     * For example, if {@code minimumNumberOfCalls} is 10, then at least 10 calls must be recorded, before the failure rate can be calculated.
+     * If only 9 calls have been recorded the CircuitBreaker will not transition to open even if all 9 calls have failed.
+     *
+     * Default minimumNumberOfCalls is 100
+     */
+    public void setMinimumNumberOfCalls(Integer minimumNumberOfCalls) {
+        this.minimumNumberOfCalls = minimumNumberOfCalls;
+    }
+
+    public Boolean getWritableStackTraceEnabled() {
+        return writableStackTraceEnabled;
+    }
+
+    /**
+     * Enables writable stack traces. When set to false, Exception.getStackTrace returns a zero length array.
+     * This may be used to reduce log spam when the circuit breaker is open as the cause of the exceptions is already known (the circuit breaker is short-circuiting calls).
+     */
+    public void setWritableStackTraceEnabled(Boolean writableStackTraceEnabled) {
+        this.writableStackTraceEnabled = writableStackTraceEnabled;
+    }
+
+    public Integer getWaitDurationInOpenState() {
+        return waitDurationInOpenState;
+    }
+
+    /**
+     * Configures the wait duration (in seconds) which specifies how long the CircuitBreaker should stay open, before it switches to half open.
+     * Default value is 60 seconds.
+     */
+    public void setWaitDurationInOpenState(Integer waitDurationInOpenState) {
+        this.waitDurationInOpenState = waitDurationInOpenState;
+    }
+
+    public Boolean getAutomaticTransitionFromOpenToHalfOpenEnabled() {
+        return automaticTransitionFromOpenToHalfOpenEnabled;
+    }
+
+    /**
+     * Enables automatic transition from OPEN to HALF_OPEN state once the waitDurationInOpenState has passed.
+     */
+    public void setAutomaticTransitionFromOpenToHalfOpenEnabled(Boolean automaticTransitionFromOpenToHalfOpenEnabled) {
+        this.automaticTransitionFromOpenToHalfOpenEnabled = automaticTransitionFromOpenToHalfOpenEnabled;
+    }
+
+    public Float getSlowCallRateThreshold() {
+        return slowCallRateThreshold;
+    }
+
+    /**
+     * Configures a threshold in percentage. The CircuitBreaker considers a call as slow when the call duration is greater than slowCallDurationThreshold(Duration.
+     * When the percentage of slow calls is equal or greater the threshold, the CircuitBreaker transitions to open and starts short-circuiting calls.
+     * <p>
+     * The threshold must be greater than 0 and not greater than 100.
+     * Default value is 100 percentage which means that all recorded calls must be slower than slowCallDurationThreshold.
+     */
+    public void setSlowCallRateThreshold(Float slowCallRateThreshold) {
+        this.slowCallRateThreshold = slowCallRateThreshold;
+    }
+
+    public Integer getSlowCallDurationThreshold() {
+        return slowCallDurationThreshold;
+    }
+
+    /**
+     * Configures the duration threshold (seconds) above which calls are considered as slow and increase the slow calls percentage.
+     * Default value is 60 seconds.
+     */
+    public void setSlowCallDurationThreshold(Integer slowCallDurationThreshold) {
+        this.slowCallDurationThreshold = slowCallDurationThreshold;
+    }
+
+    public Boolean getBulkheadEnabled() {
+        return bulkheadEnabled;
+    }
+
+    /**
+     * Whether bulkhead is enabled or not on the circuit breaker.
+     */
+    public void setBulkheadEnabled(Boolean bulkheadEnabled) {
+        this.bulkheadEnabled = bulkheadEnabled;
+    }
+
+    public Integer getBulkheadMaxConcurrentCalls() {
+        return bulkheadMaxConcurrentCalls;
+    }
+
+    /**
+     * Configures the max amount of concurrent calls the bulkhead will support.
+     */
+    public void setBulkheadMaxConcurrentCalls(Integer bulkheadMaxConcurrentCalls) {
+        this.bulkheadMaxConcurrentCalls = bulkheadMaxConcurrentCalls;
+    }
+
+    public Integer getBulkheadMaxWaitDuration() {
+        return bulkheadMaxWaitDuration;
+    }
+
+    /**
+     * Configures a maximum amount of time which the calling thread will wait to enter the bulkhead. If bulkhead has space available, entry
+     * is guaranteed and immediate. If bulkhead is full, calling threads will contest for space, if it becomes available. maxWaitDuration can be set to 0.
+     * <p>
+     * Note: for threads running on an event-loop or equivalent (rx computation pool, etc), setting maxWaitDuration to 0 is highly recommended. Blocking
+     * an event-loop thread will most likely have a negative effect on application throughput.
+     */
+    public void setBulkheadMaxWaitDuration(Integer bulkheadMaxWaitDuration) {
+        this.bulkheadMaxWaitDuration = bulkheadMaxWaitDuration;
+    }
+
+    /**
+     * Refers to an existing io.github.resilience4j.circuitbreaker.CircuitBreakerConfig instance
+     * to lookup and use from the registry.
+     */
+    public Resilience4jConfigurationProperties withConfigRef(String configRef) {
+        this.configRef = configRef;
+        return this;
+    }
+
+    /**
+     * Configures the failure rate threshold in percentage.
+     * If the failure rate is equal or greater than the threshold the CircuitBreaker transitions to open and starts short-circuiting calls.
+     * <p>
+     * The threshold must be greater than 0 and not greater than 100. Default value is 50 percentage.
+     */
+    public Resilience4jConfigurationProperties withFailureRateThreshold(Float failureRateThreshold) {
+        this.failureRateThreshold = failureRateThreshold;
+        return this;
+    }
+
+    /**
+     * Configures the number of permitted calls when the CircuitBreaker is half open.
+     * <p>
+     * The size must be greater than 0. Default size is 10.
+     */
+    public Resilience4jConfigurationProperties withPermittedNumberOfCallsInHalfOpenState(Integer permittedNumberOfCallsInHalfOpenState) {
+        this.permittedNumberOfCallsInHalfOpenState = permittedNumberOfCallsInHalfOpenState;
+        return this;
+    }
+
+    /**
+     * Configures the size of the sliding window which is used to record the outcome of calls when the CircuitBreaker is closed.
+     * {@code slidingWindowSize} configures the size of the sliding window. Sliding window can either be count-based or time-based.
+     *
+     * If {@code slidingWindowType} is COUNT_BASED, the last {@code slidingWindowSize} calls are recorded and aggregated.
+     * If {@code slidingWindowType} is TIME_BASED, the calls of the last {@code slidingWindowSize} seconds are recorded and aggregated.
+     * <p>
+     * The {@code slidingWindowSize} must be greater than 0.
+     * The {@code minimumNumberOfCalls} must be greater than 0.
+     * If the slidingWindowType is COUNT_BASED, the {@code minimumNumberOfCalls} cannot be greater than {@code slidingWindowSize}.
+     * If the slidingWindowType is TIME_BASED, you can pick whatever you want.
+     *
+     * Default slidingWindowSize is 100.
+     */
+    public Resilience4jConfigurationProperties withSlidingWindowSize(Integer slidingWindowSize) {
+        this.slidingWindowSize = slidingWindowSize;
+        return this;
+    }
+
+    /**
+     * Configures the type of the sliding window which is used to record the outcome of calls when the CircuitBreaker is closed.
+     * Sliding window can either be count-based or time-based.
+     *
+     * If {@code slidingWindowType} is COUNT_BASED, the last {@code slidingWindowSize} calls are recorded and aggregated.
+     * If {@code slidingWindowType} is TIME_BASED, the calls of the last {@code slidingWindowSize} seconds are recorded and aggregated.
+     *
+     * Default slidingWindowType is COUNT_BASED.
+     */
+    public Resilience4jConfigurationProperties withSlidingWindowType(String slidingWindowType) {
+        this.slidingWindowType = slidingWindowType;
+        return this;
+    }
+
+    /**
+     * Configures configures the minimum number of calls which are required (per sliding window period) before the CircuitBreaker can calculate the error rate.
+     * For example, if {@code minimumNumberOfCalls} is 10, then at least 10 calls must be recorded, before the failure rate can be calculated.
+     * If only 9 calls have been recorded the CircuitBreaker will not transition to open even if all 9 calls have failed.
+     *
+     * Default minimumNumberOfCalls is 100
+     */
+    public Resilience4jConfigurationProperties withMinimumNumberOfCalls(Integer minimumNumberOfCalls) {
+        this.minimumNumberOfCalls = minimumNumberOfCalls;
+        return this;
+    }
+
+    /**
+     * Enables writable stack traces. When set to false, Exception.getStackTrace returns a zero length array.
+     * This may be used to reduce log spam when the circuit breaker is open as the cause of the exceptions is already known (the circuit breaker is short-circuiting calls).
+     */
+    public Resilience4jConfigurationProperties withWritableStackTraceEnabled(Boolean writableStackTraceEnabled) {
+        this.writableStackTraceEnabled = writableStackTraceEnabled;
+        return this;
+    }
+
+    /**
+     * Configures the wait duration (in seconds) which specifies how long the CircuitBreaker should stay open, before it switches to half open.
+     * Default value is 60 seconds.
+     */
+    public Resilience4jConfigurationProperties withWaitDurationInOpenState(Integer waitDurationInOpenState) {
+        this.waitDurationInOpenState = waitDurationInOpenState;
+        return this;
+    }
+
+    public Resilience4jConfigurationProperties withAutomaticTransitionFromOpenToHalfOpenEnabled(Boolean automaticTransitionFromOpenToHalfOpenEnabled) {
+        this.automaticTransitionFromOpenToHalfOpenEnabled = automaticTransitionFromOpenToHalfOpenEnabled;
+        return this;
+    }
+
+    /**
+     * Configures a threshold in percentage. The CircuitBreaker considers a call as slow when the call duration is greater than slowCallDurationThreshold(Duration.
+     * When the percentage of slow calls is equal or greater the threshold, the CircuitBreaker transitions to open and starts short-circuiting calls.
+     * <p>
+     * The threshold must be greater than 0 and not greater than 100.
+     * Default value is 100 percentage which means that all recorded calls must be slower than slowCallDurationThreshold.
+     */
+    public Resilience4jConfigurationProperties withSlowCallRateThreshold(Float slowCallRateThreshold) {
+        this.slowCallRateThreshold = slowCallRateThreshold;
+        return this;
+    }
+
+    /**
+     * Configures the duration threshold (seconds) above which calls are considered as slow and increase the slow calls percentage.
+     * Default value is 60 seconds.
+     */
+    public Resilience4jConfigurationProperties withSlowCallDurationThreshold(Integer slowCallDurationThreshold) {
+        this.slowCallDurationThreshold = slowCallDurationThreshold;
+        return this;
+    }
+
+    /**
+     * Whether bulkhead is enabled or not on the circuit breaker.
+     */
+    public Resilience4jConfigurationProperties withBulkheadEnabled(Boolean bulkheadEnabled) {
+        this.bulkheadEnabled = bulkheadEnabled;
+        return this;
+    }
+
+    /**
+     * Configures the max amount of concurrent calls the bulkhead will support.
+     */
+    public Resilience4jConfigurationProperties withBulkheadMaxConcurrentCalls(Integer bulkheadMaxConcurrentCalls) {
+        this.bulkheadMaxConcurrentCalls = bulkheadMaxConcurrentCalls;
+        return this;
+    }
+
+    /**
+     * Configures a maximum amount of time which the calling thread will wait to enter the bulkhead. If bulkhead has space available, entry
+     * is guaranteed and immediate. If bulkhead is full, calling threads will contest for space, if it becomes available. maxWaitDuration can be set to 0.
+     * <p>
+     * Note: for threads running on an event-loop or equivalent (rx computation pool, etc), setting maxWaitDuration to 0 is highly recommended. Blocking
+     * an event-loop thread will most likely have a negative effect on application throughput.
+     */
+    public Resilience4jConfigurationProperties withBulkheadMaxWaitDuration(Integer bulkheadMaxWaitDuration) {
+        this.bulkheadMaxWaitDuration = bulkheadMaxWaitDuration;
+        return this;
+    }
+}