circuit
Component to use lightweight implementation of circuit breaker design pattern (https://martinfowler.com/bliki/CircuitBreaker.html).
Any message should not be modified in any way, just if there are many failed attempts in given circuit, then message will not be passed to target component,
exception org.openhubframework.openhub.spi.circuitbreaker.CircuitDownException is thrown instead.
URI format
circuit:<circuit-name>:<target-uri>
where
- circuit-name - unique name of circuit (could be somehow related to granularity of one target system)
- target-uri - target component to be invoked as is, if circuit is not "broken".
Usage
To keep things separated - circuit component and target component, circuit is configured by setting well defined Exchange Property.
Its name is defined constant in org.openhubframework.openhub.spi.circuitbreaker.CircuitBreaker#CONFIGURATION_PROPERTY
Usage in Camel route can look like this:
from("direct:circuit-breaker-route") .setProperty(CircuitBreaker.CONFIGURATION_PROPERTY, constant(circuitConfiguration)) .to("circuit:my-circuit:spring-ws:external-system")
With fallback handling:
from("direct:with-fallback-route") .doTry() .setProperty(CircuitBreaker.CONFIGURATION_PROPERTY, constant(circuitConfiguration)) .to("circuit:my-circuit:spring-ws:external-system") .doCatch(CircuitDownException.class) .process(<some meaningful fallback response>) .end()
Circuit breaker does work in scope of this sliding window, keeping track of failed and successful messages. Failed messages are identified by exception present, otherwise it is success.
If in each time window, some minimal threshold with relevant number of requests is exceeded, circuit does trigger, bypassing all the messages for defined time period.
Configuration
Global properties
Property | value | Description |
---|---|---|
ohf.circuitbreaker.enabled | true/false | Switch to enable entire circuit component, if set to false, nor component itself, not any CircuitBreaker implementations are initalized. Default value: false |
ohf.circuitbreaker.impl | org.openhubframework.openhub.core.circuitbreaker.CircuitBreakerInMemoryImpl org.openhubframework.openhub.core.circuitbreaker.CircuitBreakerHazelcastImpl | Implementation of org.openhubframework.openhub.spi.circuitbreaker.CircuitBreaker interface to use. Only one can be active in given time for all the circuits. See chapter Provided implementations below for details. |
For each circuit following properties are expected to be configured, as they are defined in org.openhubframework.openhub.spi.circuitbreaker.CircuitConfiguration:
Circuit configuration
Property | type | mandatory | Description |
---|---|---|---|
enabled | boolean | N | Enable or disable given circuit. Default value: true |
thresholdPercentage | int | Y | Percentage of failed requests in given window that must be exceeded in order to switch the circuit to disconnected (open) state. Value: 0-100 |
windowSizeInMillis | long | Y | Sliding window size used for evaluation. Requests out of window, are deleted. Value: millisecond count |
minimalCountInWindow | int | Y | Minimal message count in window, to consider that window relevant. This minimal number of messages in each windows is always sent. Value: count of messages |
sleepInMillis | long | Y | Sleep time, after when circuit breaker is triggered. Target uri will not be passed to this period of time. After this period, new evaluation window starts. Value: millisecond count |
Provided implementations
Out-of-box, in OHF, there are two implementations of the CircuitBreaker interface, that can be enabled just by configuration:
CircuitBreakerInMemoryImpl
ohf.circuitbreaker.impl=org.openhubframework.openhub.core.circuitbreaker.CircuitBreakerInMemoryImpl
State of all configured circuits is stored in memory. No persistence of any kind, and it is not shared between multiple instances.
CircuitBreakerHazelcastImpl
ohf.circuitbreaker.impl=org.openhubframework.openhub.core.circuitbreaker.CircuitBreakerHazelcastImpl
Does utilize Hazelcast to share circuit breaker state with all the nodes in cluster.