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