Spring Cloud: Adding Hystrix Circuit Breaker

This is a quick tutorial on Hystrix circuit break. This tutorial gives an overview of Hystrix circuit breaker component present in Spring Cloud and how we can implement it in our project.

What is Hystrix Circuit Breaker?

Hystrix circuit breaker follows the circuit breaker pattern. In layman terms, you can visualize it similar to your electrical circuit break present at your home. Firstly, Hystrix allows us to define fallback methods. Secondly, Whenever a method starts throwing errors due to any reason and it has a fallback method defined, Hystrix will invoke the fallback method rather than invoking the main method. That is it will isolate the erroneous method for time being.

TL;DR You can download whole project by clicking following link.

In this tutorial, we will be creating a spring boot application and we will be adding a fallback method using Hystrix.


Setting up Eureka Server

Since we will be creating a Eureka client we will need to have Eureka server up and running. If you have it already running then it is great. Else you can refer how to setup eureka server post or else you can download that project by using the following link.


Producer service with Hystrix fallback method

Now we will be creating a service which will have Hystrix component in it. This will be a Maven Project. Our project structure is given below. We will be creating four files which are as follows:

  1. AsmHystrixProducerApplication.java – Spring boot runable file
  2. ProducerController.java – Rest controller
  3. Student.java – Our POJO/model
  4. application.properties – Spring properties file
Project Structure

Adding Dependencies

Let’s add the required dependencies. We will need to add ‘spring-cloud-starter-netflix-hystrix‘ dependency in our project.

Replace content in pom.xml file with the following content. Don’t forget to update the project using Maven > Update option. That will download all the necessary dependencies.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.3.1.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>asm-producer</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>asm-producer</name>
	<description>Producer</description>

	<properties>
		<java.version>1.8</java.version>
		<spring-cloud.version>Hoxton.SR6</spring-cloud.version>
		<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
	</properties>

	<dependencies>
		<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.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</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>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

Creating Spring Boot Application

Create file AsmHystrixProducerApplication.java and add the following content. This file will serve as the entry point for our application.

package com.example.asmproducer;

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;

@EnableCircuitBreaker
@EnableDiscoveryClient
@SpringBootApplication
public class AsmHystrixProducerApplication {

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

}

We have added @EnableCircuitBreaker to our class. This will enable Hystrix for us.


Creating model

Create class Student.java. This will be our POJO/model class.

package com.example.asmproducer;

import java.io.Serializable;

public class Student implements Serializable {

	private int id;

	private String name;

	private String enrolledCourse;

	public Student() {
		super();
	}

	public Student(int id, String name, String enrolledCourse) {
		super();
		this.id = id;
		this.name = name;
		this.enrolledCourse = enrolledCourse;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getEnrolledCourse() {
		return enrolledCourse;
	}

	public void setEnrolledCourse(String enrolledCourse) {
		this.enrolledCourse = enrolledCourse;
	}

}

Creating Controller

Create class ProducerController.java and add the following content. This will be our rest controller and will have endpoint related stuff. In the same class, we will be defining fallback methods.

package com.example.asmproducer;

import java.util.List;
import java.util.Optional;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import com.google.common.collect.Lists;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

@RestController
public class ProducerController {

	@HystrixCommand(fallbackMethod = "getFallBackStudent")
	@GetMapping("/student/{studentId}")
	public Student getStudent(@PathVariable int studentId) {
		Optional<Student> student = getStudentRepository().stream().filter(std -> std.getId() == studentId).findAny();
		if (student.isPresent()) {
			return student.get();
		} else {
			throw new RuntimeException();
		}
	}

	public Student getFallBackStudent(int studentId) {
		return new Student(-1, "Fallback student", "NA");
	}

	@HystrixCommand(fallbackMethod = "getFallBackStudentsAll")
	@GetMapping("/student/all")
	public List<Student> getAllStudents() {
		return getStudentRepository();
	}

	public List<Student> getFallBackStudentsAll() {
		return Lists.newArrayList();
	}

	private List<Student> getStudentRepository() {
		List<Student> students = Lists.newArrayList();
		students.add(new Student(1, "Ankur", "Spring cloud"));
		students.add(new Student(2, "Tushar", "Spring boot"));
		students.add(new Student(3, "Akshay", "Spring cloud"));
		students.add(new Student(4, "Pratik", "Spring data"));
		return students;
	}

}

We have specified fallback methods using @HystrixCommand annotation. The fallback method should have the same parameters as that of the main method. In above example getStudent(…) method has getFallBackStudent(…) as fallback method and getAllStudents(…) method has getFallBackStudentsAll(…) as fallback method.


Adding Properties

Under resources folder create a file with name application.properties and add the following content.

spring.application.name=StudentProducer
eureka.client.serviceUrl.defaultZone=http://localhost:11800/eureka
eureka.instance.instanceId=:
server.port=0

That’s all. Now start Eureka server and AsmHystrixProducerApplication. You should be able to access all its endpoints as usual.

Whenever getStudent(…) or getAllStudents(…) starts throwing exceptions, Hystrix circuit breaker will get triggered and you will see fallback method getting called.


Downloads:


References:

  1. Spring Cloud- Netflix Eureka + Ribbon + Hystrix Simple Example by JavaInUse
  2. Spring Cloud- Netflix Hystrix Circuit Breaker Simple Example by JavaInUse
  3. Hystrix Circuit Breaker Pattern – Spring Cloud by HowToDoInJava
  4. Spring Cloud With Turbine by DZone
  5. Spring Cloud with Turbine AMQP by all and sundry

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.