Skip to content

spring-guides/gs-cloud-circuit-breaker

Repository files navigation

This guide walks you through the process of applying circuit breakers to potentially-failing method calls using Spring Cloud Circuit Breaker.

What You Will build

You will build a microservice application that uses the Circuit Breaker pattern to gracefully degrade functionality when a method call fails. Use of the Circuit Breaker pattern can allow a microservice to continue operating when a related service fails, preventing the failure from cascading and giving the failing service time to recover.

Starting with Spring Initializr

You can use this pre-initialized project (for the bookstore application) or this pre-initialized project (for the reading application) and click Generate to download a ZIP file. This project is configured to fit the examples in this tutorial.

To manually initialize the project:

  1. Navigate to https://start.spring.io. This service pulls in all the dependencies you need for an application and does most of the setup for you.

  2. Choose either Gradle or Maven and the language you want to use. This guide assumes that you chose Java.

  3. Click Dependencies and select Spring Reactive Web (for the service application) or Spring Reactive Web and Resilience4J (for the client application).

  4. Click Generate.

  5. Download the resulting ZIP file, which is an archive of a web application that is configured with your choices.

Note
If your IDE has the Spring Initializr integration, you can complete this process from your IDE.
Note
You can also fork the project from Github and open it in your IDE or other editor.

Set up a Server Microservice Application

The Bookstore service has a single endpoint. It is accessible at /recommended, and (for simplicity) returns a recommended reading list as a Mono of String.

The main class, in BookstoreApplication.java, looks like this:

bookstore/src/main/java/hello/BookstoreApplication.java

link:complete/bookstore/src/main/java/hello/BookstoreApplication.java[role=include]

The @RestController annotation marks BookstoreApplication as a controller class, like @Controller does, and also ensures that @RequestMapping methods in this class behave as though annotated with @ResponseBody. That is, the return values of @RequestMapping methods in this class are automatically converted appropriately from their original types and are written directly to the response body.

To run this application locally alongside a client service application, in src/main/resources/application.properties, set server.port so that the Bookstore service does not conflict with the client.

bookstore/src/main/resources/application.properties

link:complete/bookstore/src/main/resources/application.properties[role=include]

Set up a Client Microservice Application

The Reading application is our front end to the Bookstore application. We can view our reading list there at /to-read, and that reading list is retrieved from the Bookstore service application.

reading/src/main/java/hello/ReadingApplication.java

package hello;

import reactor.core.publisher.Mono;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.reactive.function.client.WebClient;

@RestController
@SpringBootApplication
public class ReadingApplication {

  @RequestMapping("/to-read")
    public Mono<String> toRead() {
      return WebClient.builder().build()
      .get().uri("http://localhost:8090/recommended").retrieve()
      .bodyToMono(String.class);
  }

  public static void main(String[] args) {
    SpringApplication.run(ReadingApplication.class, args);
  }
}

To get the list from the bookstore, we use Spring’s WebClient class. WebClient makes an HTTP GET request to the Bookstore service’s URL as we provide it and then returns the result as a Mono of String. (For more information on using Spring to consume a RESTful service using WebClient, see the Building a Reactive RESTful Web Service guide.)

Add the server.port property to src/main/resources/application.properties:

reading/src/main/resources/application.properties

link:complete/reading/src/main/resources/application.properties[role=include]

We now can access, in a browser, the /to-read endpoint on our Reading application and see our reading list. However, since we rely on the Bookstore application, if anything happens to it or if the Reading application cannot access Bookstore, we have no list and our users get a nasty HTTP 500 error message.

Apply The Circuit Breaker Pattern

Spring Cloud’s Circuit Breaker library provides an implementation of the Circuit Breaker pattern: When we wrap a method call in a circuit breaker, Spring Cloud Circuit Breaker watches for failing calls to that method and, if failures build up to a specified threshold, Spring Cloud Circuit Breaker opens the circuit so that subsequent calls automatically fail. While the circuit is open, Spring Cloud Circuit Breaker redirects calls to the method, and they are passed on to our specified fallback method.

Spring Cloud Circuit Breaker supports many different circuit breaker implementations including, Resilience4J, Hystrix, Sentinal, and Spring Retry. This guide uses the Resilience4J implementation. To use this implementation, we need to add spring-cloud-starter-circuitbreaker-reactor-resilience4j to our application’s classpath.

reading/pom.xml

link:complete/reading/pom.xml[role=include]

reading/build.gradle

link:complete/reading/build.gradle[role=include]

Spring Cloud Circuit Breaker provides an interface called ReactiveCircuitBreakerFactory, which we can use to create new circuit breakers for our application. An implementation of this interface is auto-configured, based on the starter that is on your application’s classpath. Now we can create a new service that uses this interface to make API calls to the Bookstore application:

reading/src/main/java/hello/BookService.java

link:complete/reading/src/main/java/hello/BookService.java[role=include]

The ReactiveCircuitBreakerFactory has a single method, called create, that we can use to create new circuit breakers. Once we have our circuit breaker, all we have to do is call run. The run takes a Mono or Flux and an optional Function. The optional Function parameter acts as our fallback if anything goes wrong. In our sample, the fallback returns a Mono that contains the String Cloud Native Java (O’Reilly).

With our new service in place, we can update the code in ReadingApplication to use this new service:

reading/src/main/java/hello/ReadingApplication.java

link:complete/reading/src/main/java/hello/ReadingApplication.java[role=include]

Try It

Run both the Bookstore service and the Reading service and then open a browser to the Reading service at localhost:8080/to-read. You should see the complete recommended reading list:

Spring in Action (Manning), Cloud Native Java (O'Reilly), Learning Spring Boot (Packt)

Now shut down the Bookstore application. Our list source is gone, but, thanks to Hystrix and Spring Cloud Netflix, we have a reliable abbreviated list to stand in the gap. You should see:

Cloud Native Java (O'Reilly)

Summary

Congratulations! You have developed a Spring application that uses the Circuit Breaker pattern to protect against cascading failures and to provide fallback behavior for potentially failing calls.

About

Spring Cloud Circuit Breaker Guide :: How to Use Spring Cloud Circuit Breaker

Resources

Code of conduct

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages