A demonstration of different implementations of the circuit-breaker pattern in Java to implement more resilient applications.
The following libraries are used: Failsafe, Javaslang-Circuitbreaker, Netflix Hystrix and Vert.x.
More details can be found the following blog article of mine:
http://www.hascode.com/2017/02/resilient-architecture-circuit-breakers-for-java-hystrix-vert-x-javaslang-and-failsafe-examples/
4. Micha Kops
www.hascode.com
4
Article on hasCode.com
Closed-State
● The circuit-breaker executes operations as
usual
● If a failure occurs, the circuit-breaker writes it
down
● If a specified error threshold (number of failures
or frequency of failures) is reached, it trips and
opens the circuit (transitions to the open-state)
5. Micha Kops
www.hascode.com
5
Article on hasCode.com
Open-State
● Calls to the circuit-breaker in the open state fail
immediately
● No call to the underlying operation is executed
● After a specified timeout is reached, the circuit-
breaker transitions to the half-open state.
6. Micha Kops
www.hascode.com
6
Article on hasCode.com
Half-Open-State
● In this state, one call is allowed to call the
underlying operation
● If this call fails, the circuit-breaker transitions to
the open-state again until another timeout is
reached
● If it succeeds, the circuit-breaker resets and
transitions to the closed-state.
8. Micha Kops
www.hascode.com
8
Article on hasCode.com
Failsafe - Example
UnstableApplication app = new UnstableApplication();
CircuitBreaker breaker = new CircuitBreaker().withFailureThreshold(2).withSuccessThreshold(5).withDelay(1,
TimeUnit.SECONDS);
RetryPolicy retryPolicy = new RetryPolicy().withDelay(2, TimeUnit.SECONDS).withMaxDuration(60,
TimeUnit.SECONDS)
.withBackoff(4, 40, TimeUnit.SECONDS);
System.out.printf("circuit-breaker state is: %sn", breaker.getState());
for (int i = 0; i < 10; i++) {
Thread.sleep(1000);
try {
String id = Failsafe.with(breaker).with(retryPolicy)
.onFailedAttempt((a, b) -> System.err.printf(
"failed with exception: '%s' at '%s', circuit-breaker state is: '%s'n", b,
ZonedDateTime.now(), breaker.getState()))
.onSuccess((a, b) -> System.out.printf("call succeeded, circuit-breaker state is: '%s'n",
breaker.getState()))
.get(app::generateId);
System.out.printf("FailsafeExample: id '%s' received at '%s'n", id, ZonedDateTime.now());
} catch (CircuitBreakerOpenException e) {
System.out.printf("circuit-breaker is open (state %s), time is '%s'n", breaker.getState(),
ZonedDateTime.now());
}
}
9. Micha Kops
www.hascode.com
9
Article on hasCode.com
Javaslang ExampleUnstableApplication app = new UnstableApplication();
CircuitBreakerConfig breakerConfig =
CircuitBreakerConfig.custom().ringBufferSizeInClosedState(2)
.ringBufferSizeInHalfOpenState(2).failureRateThreshold(50)
.waitDurationInOpenState(Duration.ofMillis(1000)).build();
CircuitBreaker breaker = CircuitBreaker.of("unstableAppBreaker",
breakerConfig);
Try.CheckedSupplier<String> decoratedSupplier =
Decorators.ofCheckedSupplier(app::generateId)
.withCircuitBreaker(breaker).decorate();
System.out.printf("circuit-breaker state is: %sn", breaker.getState());
for (int i = 0; i < 10; i++) {
Thread.sleep(1000);
Try<String> result = Try.of(decoratedSupplier)
.onSuccess((a) -> System.out.printf("call succeeded, circuit-
breaker state is: '%s'n",
breaker.getState()))
.onFailure(e -> System.err.printf(
"failed with exception: '%s' at '%s', circuit-breaker
state is: '%s'n", e,
ZonedDateTime.now(), breaker.getState()));
if (!result.isEmpty()) {
System.out.printf("JavaslangExample: id '%s' received at '%s'n",
result.get(), ZonedDateTime.now());
}
}
10. Micha Kops
www.hascode.com
10
Article on hasCode.com
Hystrix Example (I)
class IdGeneratingCommand extends HystrixObservableCommand<String> {
private final UnstableApplication app;
public IdGeneratingCommand(HystrixObservableCommand.Setter setter,
UnstableApplication app) {
super(setter);
this.app = app;
}
@Override
protected Observable<String> construct() {
return Observable.create(observer -> {
try {
if (!observer.isUnsubscribed()) {
observer.onNext(app.generateId());
observer.onCompleted();
}
} catch (SampleException e) {
observer.onError(e);
}
});
}
};
11. Micha Kops
www.hascode.com
11
Article on hasCode.com
Hystrix Example (II)UnstableApplication app = new UnstableApplication();
HystrixObservableCommand.Setter setter = HystrixObservableCommand.Setter
.withGroupKey(HystrixCommandGroupKey.Factory.asKey("unstableAppCmdGroup"))
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withCircuitBreakerEnabled(t
rue)
.withCircuitBreakerErrorThresholdPercentage(50)
.withCircuitBreakerSleepWindowInMilliseconds(1000).withCircuitBreakerRequestVolumeThreshold
(1));
for (int i = 0; i < 10; i++) {
CountDownLatch l = new CountDownLatch(1);
IdGeneratingCommand cmd = new IdGeneratingCommand(setter, app);
final HealthCounts healthCounts = cmd.getMetrics().getHealthCounts();
System.out.printf("circuit-breaker state is open: %s, %d errors of %d
requestsn",
cmd.isCircuitBreakerOpen(), healthCounts.getErrorCount(),
healthCounts.getTotalRequests());
Observable<String> observable = cmd.observe();
observable.subscribe(s -> {
System.out.printf("HystrixExample: id '%s' received at '%s'n", s,
ZonedDateTime.now());
} , t -> {
System.err.printf("HystrixExample: error %s, circuit-breaker state is open:
%sn", t,
cmd.isCircuitBreakerOpen());
} , () -> {
l.countDown();
});
l.await(4, TimeUnit.SECONDS);
}
12. Micha Kops
www.hascode.com
12
Article on hasCode.com
Vert.x ExampleUnstableApplication app = new UnstableApplication();
Vertx vertx = Vertx.vertx();
CircuitBreaker breaker = CircuitBreaker
.create("unstableAppBreaker", vertx,
new
CircuitBreakerOptions().setMaxFailures(2).setTimeout(2000).setFallbackOnFailure(true)
.setResetTimeout(2000))
.openHandler(h -> System.err.println("circuit-breaker opened"))
.closeHandler(h -> System.out.println("circuit-breaker closed"))
.halfOpenHandler(h -> System.err.println("circuit-breaker half-opened"));
System.out.printf("circuit-breaker state is: %sn", breaker.state());
for (int i = 0; i < 10; i++) {
Thread.sleep(1000);
breaker.<String> execute(future -> {
try {
final String id = app.generateId();
future.complete(id);
} catch (SampleException e) {
future.fail(e);
}
if (future.failed()) {
System.err.printf("failed with exception: '%s' at '%s', circuit-breaker
state is: '%s'n",
future.cause(), ZonedDateTime.now(), breaker.state());
}
}).setHandler(id -> {
if (id.succeeded())
System.out.printf("VertxExample: id '%s' received at '%s'n", id,
ZonedDateTime.now());
});
}
vertx.close();