Part 9 – Fault Tolerance with Hystrix in Microservices

Fault Tolerance in Microservices

Hystrix in Microservices

What have we learned so far,

PART 1 – MICROSERVICES INTRODUCTIONย –ย In this tutorial, we discussedย what microservices architecture is and how its different from monolithic architecture.

ย PART 2 โ€“ SCENARIO TO DEVELOPย –ย In this tutorial, we discussedย the scenario to develop.

PART 3 – FEIGN CLIENTย – In this tutorial, we discussed how feign client simplifies the rest client consumption.

PART 4 – RIBBON CLIENTย –ย In this tutorial, we discussed howย ribbon client handles the client side load balancing.

PART 5 – EUREKA NAMING SERVERย –ย In this tutorial, we discussed howย Eureka Naming Server is used to dynamically register the services at one place.

PART 6 – ZUUL GATEWAYย –ย In this tutorial, we discussed howย Zuul gateway acts as a single entry point to our application.

PART 7 – DISTRIBUTED TRACING WITH SPRING CLOUD SLEUTHย –ย In this tutorial, we discussed howย Spring sleuth used to generate logs with trace and span ids.

PART 8 – DISTRIBUTED TRACING WITH SPRING CLOUD SLEUTH & ZIPKINย –ย In this tutorial, we discussed howย Zipkin is used to see the distributed logs in microservices.

What is Hystrix?

How to handle fault tolerance in microservices?

In a distributed environment, inevitably some of the many service dependencies will fail. Hystrix is a library that helps you control the interactions between these distributed services by adding latency tolerance and fault tolerance logic. Hystrix does this by isolating points of access between the services, stopping cascading failures across them, and providing fallback options, all of which improve your systemโ€™s overall resiliency.
Hystrix is based on theย  Circuit Breaker Pattern.

Please refer the below url to understand the circuit breaker pattern and its internal states.
https://dzone.com/articles/circuit-breaker-pattern

1. Add below maven entries in pom.xml file

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
    <version>1.4.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
 <version>1.4.5.RELEASE</version>
</dependency>

2. Add @EnableHystrixDashboard & @EnableCircuitBreaker annotations in AccountServiceApp file.

package com.onlyfullstack.accountservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;

//import com.onlyfullstack.zuulgatewayservice.AlwaysSampler;

@SpringBootApplication
@EnableFeignClients
@EnableDiscoveryClient
@EnableHystrixDashboard
@EnableCircuitBreaker
public class AccountServiceApplication {

 public static void main(String[] args) {
  SpringApplication.run(AccountServiceApplication.class, args);
  
 }
}

3. In our controller we were calling customer-service api to get the customer details, lets add a fallback method for it so that in case of connection timeout or any exception came from customer-service it should return some default behavior or object.

 @GetMapping("/accounts/{account_id}")
 @HystrixCommand(fallbackMethod = "getAccountDetails_fallback")
 public Account getAccountDetails(@PathVariable Long account_id) {
  logger.debug("*** Entered in getAccountDetails with account_id: {}",account_id);
  Account account = this.listOfAccounts.stream().filter(acc -> acc.getId().equals(account_id)).findAny().orElse(null);

  Customer customer = customerServiceProxy.getCustomerDetails(account_id); // Part 3 Changes
  account.setCustomer(customer);
  logger.debug("*** Exiting from getAccountDetails with account: {}",account);
  return account;
 }

 
 public Account getAccountDetails_fallback(@PathVariable Long account_id) {
  logger.debug("*** Entered in getAccountDetails_fallback with account_id: {}",account_id);
  Account account = getDefaultAccount();
  return account;
 }

 private Account getDefaultAccount() {
  return new Account(new Long(100), null, new Double(0));
 }

4. Now start the applications in below order. Donโ€™t start customer-service so that getAccountDetails will throw connection timeout exception and it will call the fallback method to return the default object.

5. Now hit the http://localhost:8100/accounts/1 url to get the account details. This will return the default object of Account.

6. Lets check the logs. It has started the command as command: getAccountDetails and spring will keep listening to this command and if something fails then it will call the getAccountDetails_fallback method.

Source Code

Download source code of microservice with spring cloud from below git repository :
microservices-with-spring-cloud

Related Posts

Microservices Interview Questions