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

PropertyvalueDescription
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

PropertytypemandatoryDescription
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

Configuration
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

Configuration
ohf.circuitbreaker.impl=org.openhubframework.openhub.core.circuitbreaker.CircuitBreakerHazelcastImpl

Does utilize Hazelcast to share circuit breaker state with all the nodes in cluster.