Microservices often rely on each other, but what happens when a service goes down? Enter Spring Cloud Circuit Breaker, a pattern that prevents cascading failures by providing fallback mechanisms when a service is unavailable. This article focuses on integrating Spring Cloud Circuit Breaker with Feign client, a declarative HTTP client, to handle such scenarios gracefully.

1. Project Setup

Dependencies:

Start by adding the necessary dependencies to your build.gradle (Gradle) or pom.xml (Maven) file.

Gradle:

dependencies {
    implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
    implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j'
}

Maven:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>

Note: This example uses Resilience4j as the circuit breaker implementation. You can choose another implementation like Hystrix or Sentinel by replacing the spring-cloud-starter-circuitbreaker-resilience4j dependency.

2. Enabling Circuit Breaker for Feign Clients

Enable circuit breaker functionality for your Feign clients by adding the following property to your application.properties or application.yml file:

feign.circuitbreaker.enabled=true

3. Defining a Feign Client

Define a Feign client interface with the @FeignClient annotation. Specify the name of the service and the fallback class:

@FeignClient(name = "inventory-service", fallback = InventoryServiceFallback.class)
public interface InventoryServiceClient {

    @GetMapping("/inventory/{productId}")
    Inventory getInventory(@PathVariable Long productId);
}

4. Implementing the Fallback Class

Create a fallback class that implements the Feign client interface and provides alternative logic for when the service is unavailable:

@Component
public class InventoryServiceFallback implements InventoryServiceClient {

    @Override
    public Inventory getInventory(Long productId) {
        // Fallback logic, e.g., return a default value or cached data
        return new Inventory(productId, 0);
    }
}

5. Configuring the Circuit Breaker

Customize the circuit breaker behavior using Resilience4j configuration properties in your application.properties or application.yml file:

resilience4j.circuitbreaker:
  instances:
    inventory-service:
      registerHealthIndicator: true
      slidingWindowSize: 10
      failureRateThreshold: 50
      slowCallRateThreshold: 50
      slowCallDurationThreshold: 2s
      permittedNumberOfCallsInHalfOpenState: 5
      waitDurationInOpenState: 5s

This configuration sets parameters like the failure rate threshold, wait duration in open state, and the permitted number of calls in half-open state for the “inventory-service” circuit breaker.

6. Using the Feign Client

Inject the Feign client into your service and use it to make requests:

@Service
public class ProductService {

    @Autowired
    private InventoryServiceClient inventoryServiceClient;

    public Product getProduct(Long productId) {
        // ... other logic ...
        Inventory inventory = inventoryServiceClient.getInventory(productId);
        // ... use the inventory data ...
    }
}

When the “inventory-service” is unavailable or experiencing failures, the circuit breaker will open, and the getInventory() method in the InventoryServiceFallback class will be executed, providing a fallback response.

Conclusion

By integrating Spring Cloud Circuit Breaker with Feign client, you can build resilient microservices that gracefully handle service failures. This approach helps prevent cascading failures and ensures a better user experience even when dependencies are down. Remember to configure the circuit breaker with appropriate thresholds and fallback logic based on your specific needs and service requirements.


Discover more from GhostProgrammer - Jeff Miller

Subscribe to get the latest posts sent to your email.

By Jeffery Miller

I am known for being able to quickly decipher difficult problems to assist development teams in producing a solution. I have been called upon to be the Team Lead for multiple large-scale projects. I have a keen interest in learning new technologies, always ready for a new challenge.