Spring Cloud Hystrix Example

By Dhiraj Ray, 06 March,2018   0K

In this tutorial, we will be discussing about creating self healing and fault tolerance services with circuit breaker pattern using Netflix Hystrix.We will be discussing about failures in a distributed system and how Netflix spring cloud netflix hystrix helps to create such fault tolerance system using annotations such as @EnableCircuitBreaker, @HystrixCommand. At the end, we will enable hystrix dashboard within our example using @EnableHystrixDashboard.

In a distributed system, failure is inevitable.We have many micro-services that combines together to make a complete system.Sometimes, there can be a network error, or software failure or even hardware failure and this leads to a cascading failure in a distributed system. In these scenarios, a common way to prevent cascading failure is to use circuit breaker pattern.It is a design pattern used in modern software development. It is used to detect failures and encapsulates the logic of preventing a failure from constantly recurring, during maintenance, temporary external system failure or unexpected system difficulties.

Spring cloud helps to build fault tolerance system by implementing Netflix Hystrix.It is a latency and fault tolerance library designed to isolate points of access to remote systems, services and 3rd party libraries, stop cascading failure and enable resilience in complex distributed systems where failure is inevitable.Hystrix implements circuit breaker pattern.It wraps service calls and watches for failures and provides a default rolling window for 10 seconds.For a 20 request volume, if the error rate is more than 20% then the service is tripped and no request is allowed through.

In this tutorial, we will be building a spring cloud app using Netfli Hystrix. This app will have a eureka dicovery server that we built in our last example - Spring Cloud Netflix Eureka and an eureka service and eureka client. All the Hystrix implementation will be in our client service and our client app will be a fault tolerance system against the unavailability of our service. During unavailability of our service, a fallback method will be invoked with the hystrix command.

Spring Cloud Discovery Server

We will be using our existing discovery server implementation on github. Following is the application.properties file and DiscoveryServerApplication.javathat we used while implementing discovery server in our last example.

application.properties
spring.application.name=discovery-server
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
server.port=8761
DiscoveryServerApplication.java
@EnableEurekaServer
@SpringBootApplication
public class DiscoveryServerApplication {

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

Spring Cloud Eureka Service

Now we will be creating a sample microservice that will register itself to discovery server.Let us generate a spring boot project from http://start.spring.io

netflix-eureka-service

This brings following maven dependencies.

pom.xml
<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
	</dependency>

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>

<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-dependencies</artifactId>
			<version>${spring-cloud.version}</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>

Now, let us define our application.properties.spring.application.name is the unique identifier for this service and eureka.client.service-url.defaultZone is the url of service discvery server.

spring.application.name=netflix-service
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
server.port=8085

Following is our spring boot application class.We want our service to be registered on discovery server and hence the annotation @EnableDiscoveryClient

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class NetflixServiceApplication {

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

Now we will have an endpoint exposed at /demo

@RestController
public class DemoController {

    @GetMapping("/demo")
    public String Demo(){
        return "demo";
    }
}

Spring Cloud Netflix Hystrix

This will be our eureka client app. Let us generate it from http://start.spring.io

netflix-eureka-client

This brings following maven dependencies.

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-actuator</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
	</dependency>

	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
</dependencies>

<dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-dependencies</artifactId>
			<version>${spring-cloud.version}</version>
			<type>pom</type>
			<scope>import</scope>
		</dependency>
	</dependencies>
</dependencyManagement>

Now let us define our spring boot application class.@EnableCircuitBreaker tells Spring Cloud that the Reading application uses circuit breakers and to enable their monitoring, opening, and closing (behavior supplied, in our case, by Hystrix).

@SpringBootApplication
@EnableCircuitBreaker
@EnableDiscoveryClient
public class NetflixClientApplication {

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

Following is the application.properties

application.properties
spring.application.name=netflix-client
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
server.port=9090

Now, let us expose sample endpoint in the client project.

@RestController
public class ClientController {

    @Autowired
    private ClientService clientService;

    @GetMapping("/test")
    public String test(){
        return clientService.test();
    }
}

Now we will be using @HystrixCommand to define our fallback method for any unavailability of our service.@HystrixCommand only works in a class marked with @Component or @Service and hence we following service defined.We have @HystrixCommand annotated on test() and hence when our service call fails the fallback method will be executed.

ClientService.java
@Service
public class ClientService {

    @Autowired
    private EurekaClient eurekaClient;

    @HystrixCommand(fallbackMethod = "failed")
    public String test(){
        InstanceInfo instanceInfo = eurekaClient.getNextServerFromEureka("netflix-service", false);
        String serviceBaseUrl = instanceInfo.getHomePageUrl();
        String result = new RestTemplate().getForObject(serviceBaseUrl + "demo", String.class);
        return result;
    }

    public String failed(){
        return "failed";
    }
}

Test Spring Cloud netflix Hystrix

Now let us start our discovery server, netflix eureka service and client in a row and hit http://localhost:9090/test

netflix-hystrix-success-result

Now we will stop the service and hit the url again and this time the fallback method will be invoked.

netflix-hystrix-failure-result

Hystrix Dashboard

Hystrix dashboard is a web application that provides a dashboard for monitoring applications using Hystrix.Hystrix dashboard is not intended to be deployed on untrusted networks, or without external authentication and authorization. To enable Hystrix dashboard, we only have to annotate our spring boot main class with @EnableHystrixDashboard. Following is the dependency information of Hystrix project.

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

Conclusion

In this article, we discussed about implementing spring cloud netflix hystrix to build a fault tolerance system using circuit breaker pattern.The source can be downloaded from here.If you have anything that you want to add or share then please share it below in the comment section

1. Spring Cloud Config

2. Spring Cloud Netflix Eureka

3. Introduction To Microservices

4. Refresh Property Config Runtime

If You Appreciate What We Do Here On Devglan, You Should Consider: