Spring Cloud: Playing with Hystrix Circuit Breaker

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.

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.