Circuit Breaker Implementation in Java EE  

 

Introduction

One of the common patterns used when calling remote functions is the circuit breaker pattern. It is described by Martin Fowler and also in the book ‘Release It’ of Michael Nygard. The cicruit breaker acts like a circuit breaker in real life. You wrap a remote function call in a circuit breaker which monitors for failures. Once the failures reach a certain threshold the circuit breaker trips and all further calls to the circuit breaker return with an error, without the protected call being made at all. An extra feature is the automatic closure of the circuit breaker; With the next request, after a certain sleep time, the protected function is called once (half-open state). When this service call succeeds, the circuit breaker is closed and the protected function will be called again on each request.

Other implementations

Various circuit breaker implementations are already on the web. Netflix presented a complete set of java libraries including a circuit breaker with Hystrix. Hystrix also provides a circuitbreaker, including monitoring metrics with the hystrix-dashboard. It uses the command pattern to wrap the protected funtion. However this is based on Java 6, therefore it is not using lambda’s (java 8). Neither it is using the Java EE api.

Java EE solution

We present a solution purely based on Java EE functionality, using the ManagedExecutorService and CDI .

Usage:

A circuit breaker can be injected :

@Inject
private CircuitBreaker<String> circuitBreaker;

then the service that needs to be protected should be called through the circuit breaker with a lambda expression:

circuitBreaker.call(SlowSupplier::supplierMethod)

where SlowSupplier provides (an example) of a protected function. The circuit breaker is eventually configured at the injection point using the CircuitBreakerConfig annotation :

@Inject
@CircuitBreakerConfig(timeOut = 5000, errorsThreshold = 3, sleepWindow = 4000)
private CircuitBreaker<String> configuredCircuitBreaker;

In this configuration the circuitbreaker (via the executor service) will give a timeout error after 5 seconds. After 3 such calls, the circuit wil be opened, so that each following call will give a CircuitBreakerException instantaneously. Afther being open for 4 seconds the circuit breaker will retry the slow supplier method. When this is successfull the circuit breaker will be closed again.

Implementation:

The circuit breaker is created by the CircuitBreakerProducer:

@Produces
public <T> CircuitBreaker<T> createCircuitBreaker(InjectionPoint injectionPoint)

T is the class of the object the supplier method returns. In the producer a circuit breaker is created. The injectionPoint parameter is used to query the CircuitBreakerConfig  at the injection point.

The implementation uses the managed executor service for submitting the call asynchroneously and setting the timeout :

Future<T> task = executorService.submit(supplier::get);
try {
T result = task.get(timeOut, TimeUnit.MILLISECONDS);
return result;
catch (TimeoutException ex) {
task.cancel(true);
throw onError(ex);

If the timeout exception is catched, the submitted task is cancelled, and in the onError method the errors are counted, eventually opening the circuit breaker when the threshold is reached. The TimeOutException is wrapped in the CircuitBreakerException. In our code actually every service error is catched and wrapped, but this is optional.

Also the automatic closing of the circuit breaker is implemented by checking the time elapsed (before submitting the call) since the last error. If this is larger than the sleepwindow the circuit breaker is put in halfopen state :

if ((System.currentTimeMillis() - lastErrorTime) > sleepWindow) {
state = HALFOPEN;

The managed executor service can be configured in the application server, e.g. for setting the size of the used threadpool . See this blog for an example.

The slow supplier is simulated with a Thread.sleep() which also can be set with a rest endpoint.

For demonstration purposes a caller with a default circuit breaker (omitting the config annotation) and a advanced caller with a configured circuit breaker injected aren given as rest endpoints. The example url’s for calling these callers are in the index.html . Also the state of the injected circuit breaker can be read and set using these endpoints. This demonstration can be found in the repo.

References

For Martin Fowlers blog on Circuit Breaker see:

http://martinfowler.com/bliki/CircuitBreaker.html

For a reference to creating a managedExecutorService see:

Leave a Reply

Your email address will not be published. Required fields are marked *