In this tutorial, we will set up a Spring Boot application that uses Spring Cloud Circuit Breaker to handle service failures gracefully. We will demonstrate its real use by creating two microservices (ProductService
and OrderService
) and applying a circuit breaker to the OrderService
when it calls the ProductService
.
Prerequisites
- JDK 17 or higher
- Maven or Gradle
- IDE (e.g., IntelliJ IDEA, Eclipse)
- Basic knowledge of Spring Boot
What is a Circuit Breaker?
A circuit breaker is a design pattern used in microservices architecture to prevent cascading failures and provide fallback mechanisms. When a service call fails repeatedly, the circuit breaker trips and directs the calls to a fallback method, thereby preventing further failures and allowing the system to recover gracefully.
Key Benefits
- Fault Tolerance: Prevents cascading failures by stopping the flow of requests to a failing service.
- Fallback Mechanisms: Provides alternate responses when a service fails.
- Resilience: Enhances the overall resilience of the system by isolating failures.
Setting Up Spring Cloud Circuit Breaker
Step 1: Create ProductService
Microservice
1.1: Using Spring Initializr to Create the Project
- Go to Spring Initializr.
- Set the project metadata:
- Group:
com.example
- Artifact:
product-service
- Name:
Product Service
- Description:
E-commerce Product Service
- Package Name:
com.example.productservice
- Packaging:
Jar
- Java:
17
(or higher)
- Group:
- Add dependencies:
- Spring Web
- Click on Generate to download the project.
- Unzip the downloaded project and open it in your IDE.
1.2: Define the Product Model
Create a new class Product
in src/main/java/com/example/productservice
:
package com.example.productservice;
public class Product {
private Long id;
private String name;
private double price;
// Constructors, getters, and setters
public Product() {}
public Product(Long id, String name, double price) {
this.id = id;
this.name = name;
this.price = price;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
1.3: Create a ProductController
Create a new class ProductController
in src/main/java/com/example/productservice
:
package com.example.productservice;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ProductController {
@GetMapping("/products/{id}")
public Product getProductById(@PathVariable Long id) {
// For simplicity, returning a hardcoded product. In a real application, you'd query the database.
return new Product(id, "Sample Product", 99.99);
}
}
1.4: Run ProductService
Ensure the main application class is set up correctly:
package com.example.productservice;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ProductServiceApplication {
public static void main(String[] args) {
SpringApplication.run(ProductServiceApplication.class, args);
}
}
Step 2: Create OrderService
Microservice
2.1: Using Spring Initializr to Create the Project
- Go to Spring Initializr.
- Set the project metadata:
- Group:
com.example
- Artifact:
order-service
- Name:
Order Service
- Description:
E-commerce Order Service
- Package Name:
com.example.orderservice
- Packaging:
Jar
- Java:
17
(or higher)
- Group:
- Add dependencies:
- Spring Web
- Spring Cloud Circuit Breaker
- Spring Boot Starter Actuator (for monitoring)
- Click on Generate to download the project.
- Unzip the downloaded project and open it in your IDE.
2.2: Add Spring Cloud Circuit Breaker Dependency
Add the following dependency to your pom.xml
:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
2.3: Define the Order Model
Create a new class Order
in src/main/java/com/example/orderservice
:
package com.example.orderservice;
public class Order {
private Long id;
private String product;
private int quantity;
// Constructors, getters, and setters
public Order() {}
public Order(Long id, String product, int quantity) {
this.id = id;
this.product = product;
this.quantity = quantity;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getProduct() {
return product;
}
public void setProduct(String product) {
this.product = product;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
2.4: Create a ProductServiceClient
Create a new class ProductServiceClient
in src/main/java/com/example/orderservice
to call the ProductService
:
package com.example.orderservice;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Component
public class ProductServiceClient {
private final RestTemplate restTemplate;
public ProductServiceClient(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
public Product getProductById(Long id) {
return restTemplate.getForObject("http://localhost:8081/products/" + id, Product.class);
}
}
2.5: Create a RestTemplate Bean
Add a RestTemplate
bean to the OrderService
application:
package com.example.orderservice;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class AppConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
2.6: Create an OrderController with Circuit Breaker
Create a new class OrderController
in src/main/java/com/example/orderservice
and use Spring Cloud Circuit Breaker:
package com.example.orderservice;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderController {
private final ProductServiceClient productServiceClient;
public OrderController(ProductServiceClient productServiceClient) {
this.productServiceClient = productServiceClient;
}
@CircuitBreaker(name = "productService", fallbackMethod = "fallbackGetProductById")
@GetMapping("/orders/{id}")
public Order getOrderById(@PathVariable Long id) {
Product product = productServiceClient.getProductById(id);
return new Order(id, product.getName(), 2);
}
public Order fallbackGetProductById(Long id, Throwable throwable) {
return new Order(id, "Fallback Product", 0);
}
}
Step 3: Run and Test the Microservices
-
Start
ProductService
:- Run the
ProductServiceApplication
main class. - Verify it is running by accessing
http://localhost:8081/products/1
in your browser. You should see a sample product response.
- Run the
-
Start
OrderService
:- Run the
OrderServiceApplication
main class. - Verify it is running by accessing
http://localhost:8082/orders/1
in your browser. You should see an order response with product details.
- Run the
-
Simulate a Failure:
- Stop the
ProductService
. - Access
http://localhost:8082/orders/1
in your browser. You should see the fallback response with the "Fallback Product" and quantity 0.
- Stop the
Conclusion
Spring Cloud Circuit Breaker provides a robust and easy-to-use solution for handling service failures gracefully. By following this tutorial, you've learned how to set up two microservices (ProductService
and OrderService
) and apply a circuit breaker to manage failures in the OrderService
when calling the ProductService
. This setup enhances the resilience and fault tolerance of your microservices architecture, ensuring that failures are handled gracefully and the overall system remains stable.
Comments
Post a Comment
Leave Comment