Spring Cloud: Playing with Hystrix Circuit Breaker

⚠️ This tutorial is outdated. Netflix Hystrix has been in maintenance mode since 2018 and was removed from Spring Cloud — it does not work with Spring Boot 3.x. For current projects, use Resilience4j instead, and see the Spring Cloud Netflix migration guide for the full modern stack. This post remains online for teams maintaining legacy systems.

This tutorial is a continuation of Spring Cloud: Adding Hystrix Circuit Breaker. In the previous tutorial, we had an overview of Hystrix circuit breaker and we have implemented the same in our producer application. Now in this tutorial, we will see it in action.


Setting up Eureka Server

Since we will be working with Spring cloud, we will need Eureka server up and running. Either you can refer Setting Up Eureka Server Using Spring Cloud post which has detailed step by step explanation of it or you can download the following project and run it directly.


Producer service with Hystrix fallback method

Now we will be making some changes in producer project which we created in Spring Cloud: Adding Hystrix Circuit Breaker tutorial. We will be adding a few sysout (System.out.println) statements in our ProducerController.java class. I have highlighted those statements in the following code.

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) {
		System.out.println("Fetching Students");
		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) {
		System.out.println("Fallback method");
		return new Student(-1, "Fallback student", "NA");
	}

	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;
	}

}

Or you can download this updated project by clicking on following link.


Updating consumer project

To see Hystrix circuit breaker in action we will need consumer/client as well. For that we will be using consumer/client created in Spring Cloud: Creating REST Client Using Ribbon project.

In this case, we will be accessing ‘/student/{studentId}’ endpoint of the producer. We will be accessing that endpoint 100 times. We will be passing studentId 1 to 100 one by one internally. I have highlighted the code which needs to be modified in below snippet. Please do those modifications in ConsumerController.java.

package com.example.asmribbonconsumer;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class ConsumerController {

	@Autowired
	private LoadBalancerClient loadBalancer;

	@GetMapping("/studentdetails/all")
	public String letsSayHello() {
		ServiceInstance serviceInstance = loadBalancer.choose("StudentProducer");
		System.out.println(serviceInstance.getUri());

		String baseUrl = serviceInstance.getUri().toString();
		baseUrl = baseUrl + "/student";

		for (int i = 1; i <= 100; i++) {
			RestTemplate restTemplate = new RestTemplate();
			ResponseEntity<Student> response = restTemplate.getForEntity(baseUrl + "/" + i, Student.class);
		}

		return "Done";
	}

}

In case if you are looking for full project, you can download it by clicking on the following link.


Testing it

Now run all three projects viz, Eureka Server, Producer application and consumer application together. Once all three projects are up, navigate to ‘http://localhost:11802/studentdetails/all’. This will invoke the consumer/client and will start accessing producer API internally for studentId 1 to 100.

Now check console output. We can clearly see that initially getStudent(…) method was executing and it was printing ‘Fetching Students’ on the console. But since we have only 4 students in our repository, from studentId 5 onward we started receiving exception.

Once we started receiving exception, Hystrix got kicked in. Since we were continuously receiving exception, Hystrix passed our request to fallback method i.e. getFallBackStudent(…). And we started receiving ‘Fallback method’ on the console.

Console Output

Also, note that Hystrix didn’t start executing fallback method right away. Initially, it was switching between main method and fallback method for a few requests. But the main method was continuously throwing exceptions, Hystrix switched to fallback method permanently after few requests.

What you observed in the console is the circuit moving through its three states. While failures are below the threshold, the circuit is CLOSED and every request still reaches the main method — that is the early phase where both messages alternate. Once the failure rate crosses Hystrix’s threshold (by default, 50% of requests within a rolling window, with a minimum request volume), the circuit goes OPEN and calls are short-circuited straight to the fallback without touching the main method at all — the phase where you see only ‘Fallback method’. After a sleep window, Hystrix would let one trial request through (HALF-OPEN) to test whether the producer has recovered; success closes the circuit again, failure re-opens it.

This is how the Hystrix circuit breaker functionality works. Hope you have understood.


Downloads:

Leave a Reply

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