- When should the circuit trip?
- Last
n
request to consider for this decision - How many of those should fail
- Timeout duration
- When does the circuit comes back online again?
- Last n request to consider for the decision: 5
- How many of this should fail: 2
- Timeout duration: 3s
- How long to wait [sleeping window]: 10s
Tuning these numbers are tricky. Things to consider:
req/sec
- Number of thread pool of the server
- tune based on trial and error and stat
Hystrix Proxy class
We use @CircuitBreaker
command in class level. In the root of Spring Boot class. Then inside a @Service
class, we annotate a method with @HystrixCommand
and mention a fallback method.
Problem with this is everything is happening inside our API class
. But when we annotate the class, every time we refer the instance of the class, we actually refer the Hystrix Proxy class
.
So, when the circuit trips, we want the Hystrix Proxy
class to intercept the call and fall back to the default method. But it does not happen. Because everything is happening inside our API class.
That's why we need to use the @HystrixCommand
in a separate class and use that class's instance. That way we get the Hystrix wrapper instance.
@Service
@Slf4j
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {
private final PaymentServiceAPI paymentServiceAPI;
@Override
public OrderCheckOutResponse checkoutOrder(OrderCheckOutRequest orderCheckOutRequest) {
log.info("Dumping into db {}", orderCheckOutRequest);
PaymentAPIResponse paymentAPIResponse = makePayment(orderCheckOutRequest);
var orderCheckOutResponse = OrderCheckOutResponse.builder();
if (paymentAPIResponse.getCode() == 333) {
orderCheckOutResponse
.code(paymentAPIResponse.getCode())
.message(paymentAPIResponse.getMessage());
} else {
orderCheckOutResponse
.code(555)
.message("Payment failed");
}
return orderCheckOutResponse.build();
}
@HystrixCommand(fallbackMethod = "defaultMakePayment")
private makePayment(OrderCheckOutRequest orderCheckOutRequest) {
return paymentServiceAPI.makePayment(orderCheckOutRequest)
}
public PaymentAPIResponse defaultMakePayment(OrderCheckOutRequest orderCheckOutRequest) {
log.info("Hystrix Fall back payment method called");
return PaymentAPIResponse.builder()
.code(555)
.message("Payment failed")
.build();
}
}
[PaymentServiceImpl.java](http://paymentserviceimpl.java)
@Service
@Slf4j
@RequiredArgsConstructor
public class PaymentServiceImpl implements PaymentService {
private final PaymentServiceAPI paymentServiceAPI;
@Override
@HystrixCommand(fallbackMethod = "defaultMakePayment")
public PaymentAPIResponse makePayment(OrderCheckOutRequest orderCheckOutRequest) {
return paymentServiceAPI.makePayment(getPaymentAPIRequest(orderCheckOutRequest));
}
private PaymentAPIRequest getPaymentAPIRequest(OrderCheckOutRequest orderCheckOutRequest) {
return PaymentAPIRequest.builder()
.userID(orderCheckOutRequest.getUserID())
.amount(orderCheckOutRequest.getAmount())
.build();
}
public PaymentAPIResponse defaultMakePayment(OrderCheckOutRequest orderCheckOutRequest) {
log.info("Hystrix Fall back payment method called");
return PaymentAPIResponse.builder()
.code(555)
.message("Payment failed")
.build();
}
}
[OrderServiceImpl.java](http://orderserviceimpl.java)
@Service
@Slf4j
@RequiredArgsConstructor
public class OrderServiceImpl implements OrderService {
private final PaymentService paymentService;
@Override
public OrderCheckOutResponse checkoutOrder(OrderCheckOutRequest orderCheckOutRequest) {
log.info("Dumping into db {}", orderCheckOutRequest);
PaymentAPIResponse paymentAPIResponse = paymentService.makePayment(orderCheckOutRequest);
var orderCheckOutResponse = OrderCheckOutResponse.builder();
if (paymentAPIResponse.getCode() == 333) {
orderCheckOutResponse
.code(paymentAPIResponse.getCode())
.message(paymentAPIResponse.getMessage());
} else {
orderCheckOutResponse
.code(555)
.message("Payment failed");
}
return orderCheckOutResponse.build();
}
}
Spring Boot Microservices Level 2: Fault Tolerance and Resilience