Spring Boot Microservices — Implementing Circuit Breaker

In this article, we will learn the fundamentals of one of the must pattern in the Microservices world — Circuit Breaker. We will do the sample implementation based on Spring Boot, Spring Cloud & Resilience4j. This is the sixth part of our Spring Boot Microservices series.

Lal Verma
Lal Verma
Sep 21, 2020 · 10 min read
Image for post
Image for post

What is Circuit Breaker?

Image for post
Image for post
Get Product Details — Api

How does the pattern work?

Image for post
Image for post
Circuit Breaker — An Illustration

Sample Implementation

Building Product Inventory Service

Image for post
Image for post
spring initializer — product-inventory service
@RestController
public class ProductInventoryService {
@Autowired
private ReactiveMongoTemplate mongoTemplate;
@PostMapping("/inventory")
public Mono < ProductInventory > addProductInventory(@RequestBody ProductInventory product) {
return mongoTemplate.insert(product);
}
@PutMapping("/inventory")
public Mono < ProductInventory > updateProductInventory(@RequestBody ProductInventory product) {
return mongoTemplate.save(product);
}
@GetMapping("/inventory/{id}")
public Mono < ProductInventory > getProductInventory(@PathVariable String id) {
return mongoTemplate.findById(id, ProductInventory.class);
}
}
public class ProductInventory {
@Id
private String productId;
private int quantity;
//getters and setters ... }
server.port=8082
spring.data.mongodb.uri=mongodb+srv://xxx-user:xxx-pwdY@cluster0.nrsv6.gcp.mongodb.net/ecommerce
{
"productId": "test-product-123",
"quantity": 30
}

Building Product Catalog Service

Image for post
Image for post
spring initializer — Product Catalog Service
@RestController
public class ProductCatalogService {
@Autowired
private ReactiveMongoTemplate mongoTemplate;
@Autowired
private WebClient webClient;
@Autowired
private ReactiveCircuitBreakerFactory cbFactory;
@GetMapping("/product/{id}")
public Mono < ProductDetails > getProductDetails(@PathVariable String id) {
Mono < ProductDetails > productDetailsMono = mongoTemplate.findById(id, ProductDetails.class);Mono < ProductInventory > inventoryMono = webClient.get().uri("http://localhost:8082/inventory/" + id).retrieve()
.bodyToMono(ProductInventory.class);
Mono < ProductDetails > mergedProductDetails = Mono.zip(productDetailsMono, inventoryMono,
(productDetails, inventory) - > {
productDetails.setInventory(inventory);
return productDetails;
});
return mergedProductDetails;
}
@PostMapping("/product")
public Mono<Product> addProduct(@RequestBody Product product){
return mongoTemplate.insert(product);
}
...
}
{
"id":"test-product-123",
"title":"test-product-1",
"desc":"test product 1",
"imagePath":"gc://image-path",
"unitPrice":10.00
}
{
"id":"test-product-123",
"title":"test product for circuit breaker",
"desc":"test product updated",
"imagePath":"gc://image-path",
"unitPrice":10.0,
"inventory":{
"productId":"test-product-123",
"quantity":30
}
}

Implementing Circuit Breaker

[70118947-6] There was an unexpected error (type=Internal Server Error, status=500).
@RestController
public class ProductCatalogService {

@Autowired
private ReactiveCircuitBreakerFactory cbFactory;
@GetMapping("/product/{id}")
public Mono < ProductDetails > getProductDetailsV2(@PathVariable String id) {
Mono < ProductDetails > productDetailsMono = mongoTemplate.findById(id, ProductDetails.class);
Mono < ProductInventory > inventoryMono = webClient.get()
.uri("http://localhost:8082/inventory/" + id)
.retrieve()
.bodyToMono(ProductInventory.class)
.transform(
it - > cbFactory.create("inventory-service")
.run(it,
throwable - > {
return Mono.just(new ProductInventory());
}
)
);
Mono < ProductDetails > mergedProductDetails = Mono.zip(productDetailsMono, inventoryMono, (productDetails, inventory) - > {
productDetails.setInventory(inventory);
return productDetails;
});
return mergedProductDetails;
}
}

When the exception occurs in the call, its returning blank ProductInventory object.

resilience4j.circuitbreaker:
instances:
inventory-service:
failureRateThreshold: 50
minimumNumberOfCalls: 20
slidingWindowType: TIME_BASED
slidingWindowSize: 10
waitDurationInOpenState: 50s
permittedNumberOfCallsInHalfOpenState: 3
{
"id": "test-product-123",
"title": "test-product-123_1",
"desc": "test product updated",
"imagePath": "gc://image-path",
"unitPrice": 10,
"inventory": {
"productId": null,
"quantity": 0
}
}
Image for post
Image for post

Next Steps

You can browse1. Next Exercise - Kubernetes-ization.

2. Complete Series - Spring Boot Microservices - Learning through Examples
3. Previous Exercise - Implementing Api GatewayComplete source code of the sample implementation is available at Github

The Startup

Medium's largest active publication, followed by +755K people. Follow to join our community.

Lal Verma

Written by

Lal Verma

Technology Evangelist | Microservices Architecture, Cloud Technologies, Enterprise Softwares

The Startup

Medium's largest active publication, followed by +755K people. Follow to join our community.

Lal Verma

Written by

Lal Verma

Technology Evangelist | Microservices Architecture, Cloud Technologies, Enterprise Softwares

The Startup

Medium's largest active publication, followed by +755K people. Follow to join our community.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store