1

Context

I'm developing a project based on a microservices architecture. The communication between them happens like this: Client send a request to the API Gateway that routes the request to the first service called serviceA; this one, forward the request to a second service called serviceB, and so on up to serviceD. So these microservices are like a service chain.

I'm using:

  • Eureka as service registry

  • Spring Cloud Gateway as API Gateway

  • Prometheus and Grafana for metrics aggregation and visualization

  • Docker for containerization (and a docker-compose file)

  • Spring Cloud Circuitbreaker

  • Spring Cloud Version: 2021.0.5

  • Spring Boot Version: 2.7.9

  • JRE Version: 1.8

Problem

I tried to use the @CircuitBreaker annotation to implement a circuitbreaker pattern on the method that forwards the request from serviceA to serviceB, so that if serviceB is down or there are other issues, a fallback method will be called to return a fallback string. However, when i run the containers and try to stop the serviceB container to test the fallback method i get a 500 status code, and no fallback message.

If I use instead a CircuitBreakerFactory to implement the circuitbreaker pattern, it works.

What i tried to do to solve the problem

  • Adding different circuitbreaker configs in the application.yml
  • Changing maven dependencies
  • Changing Spring Cloud version
  • Changing JRE version

Code Snippets

ServiceAServiceImplementation.java with @CircuitBreaker annotation implementation

@Service
public class ServiceAServiceImplementation implements ServiceAService {

    @Value("${serviceBUrl}")
    private String serviceBUrl;

    private Logger logger = Logger.getLogger(ServiceAServiceImplementation.class.getName());

    private final RestTemplate restTemplate;

    public ServiceAServiceImplementation (RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @Override
    public String getIBM() {
        return "IBM";
    }

    @Override
    @CircuitBreaker(name = "breakerAtoB", fallbackMethod = "getInfoFallbackAtoB")
    public String callB() {
        return restTemplate.getForEntity(serviceBUrl + "/getCloud", String.class).getBody();
    }

    public String getInfoFallbackAtoB(Throwable t) {
        logger.log(Level.SEVERE, "[Fallback (ServizioA)]: Errore durante la chiamata al servizio B: " + t.getMessage(), t);
        return "[Fallback] Cloud Academy Marzo 2023";
    }
}

ServiceAServiceImplementation.java with CircuitBreakerFactory implementation

@Value("${serviceBUrl}")
    private String serviceBUrl;

    private Logger logger = Logger.getLogger(ServiceAServiceImplementation.class.getName());

    private final RestTemplate restTemplate;
    private final CircuitBreakerFactory circuitBreakerFactory;

    public ServiceAServiceImplementation (RestTemplate restTemplate, CircuitBreakerFactory circuitBreakerFactory) {
        this.restTemplate = restTemplate;
        this.circuitBreakerFactory = circuitBreakerFactory;
    }

    @Override
    public String getIBM() {
        return "IBM";
    }

    @Override
    public String callB() {
        return circuitBreakerFactory.create("breakerAtoB", "breakerAtoB").run(() -> restTemplate.getForEntity(serviceBUrl + "/getCloud", String.class).getBody(),
          throwable -> getInfoFallbackAtoB(throwable));
    }

    public String getInfoFallbackAtoB(Throwable t) {
        logger.log(Level.SEVERE, "[Fallback (ServizioA)]: Errore durante la chiamata al servizio B: " + t.getMessage(), t);
        return "[Fallback] Cloud Academy Marzo 2023";
    }

serviceA pom.xml file

<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 
 <modelVersion>4.0.0</modelVersion> 
 <parent> 
  <groupId>org.springframework.boot</groupId> 
  <artifactId>spring-boot-starter-parent</artifactId> 
  <version>2.7.9</version> 
  <relativePath/> <!-- lookup parent from repository --> 
 </parent> 
 <groupId>com.academy.cic</groupId> 
 <artifactId>serviceA</artifactId> 
 <version>0.0.1-SNAPSHOT</version> 
 <name>serviceA</name> 
 <description>Primo esercizio</description> 
  
 <properties> 
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 
  <java.version>1.8</java.version> 
  <spring-cloud.version>2021.0.5</spring-cloud.version> 
 </properties> 
 <dependencyManagement> 
  <dependencies> 
   <dependency> 
    <groupId>org.springframework.cloud</groupId> 
    <artifactId>spring-cloud-dependencies</artifactId> 
    <version>${spring-cloud.version}</version> 
    <type>pom</type> 
    <scope>import</scope> 
   </dependency> 
  </dependencies> 
 </dependencyManagement> 
  
 <dependencies> 
         
  <dependency> 
      <groupId>org.springframework.cloud</groupId> 
      <artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId> 
  </dependency> 
   
  <dependency> 
      <groupId>org.springframework.cloud</groupId> 
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> 
  </dependency> 
   
  <dependency> 
       <groupId>org.springframework.boot</groupId> 
       <artifactId>spring-boot-starter-actuator</artifactId> 
  </dependency> 
     
  <dependency> 
       <groupId>io.github.resilience4j</groupId> 
       <artifactId>resilience4j-micrometer</artifactId> 
  </dependency> 
   
  <dependency> 
      <groupId>io.micrometer</groupId> 
      <artifactId>micrometer-registry-prometheus</artifactId> 
  </dependency> 
   
  <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-web</artifactId> 
  </dependency> 
 
  <dependency> 
      <groupId>org.springframework.boot</groupId> 
      <artifactId>spring-boot-starter-test</artifactId> 
      <scope>test</scope> 
  </dependency> 
   
 </dependencies> 
 
 <build> 
  <plugins> 
   <plugin> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-maven-plugin</artifactId> 
   </plugin> 
  </plugins> 
 </build> 
 
</project>
  • Does this answer your question? [Use Annotation with Spring Cloud Circuit Breaker - Resilience4j](https://stackoverflow.com/questions/58121602/use-annotation-with-spring-cloud-circuit-breaker-resilience4j) – Chin Huang Mar 23 '23 at 14:57
  • Try with `spring-cloud-starter-circuitbreaker-resilience4j` (no reactor) since you aren't using `spring-boot-starter-webflux`. – spencergibb Mar 23 '23 at 15:43

0 Answers0