Hystrix Circuit breaker pattern with Spring Boot

In this article, we will go through how to implement the circuit breaker design pattern using Hystrix and Spring Boot

What is Hystrix?

Hystrix is the fault tolerance library. Using this library we can implement a circuit breaker design pattern. Hystrix is watching methods for failing calls to related services. If there is such a failure, it will open the circuit and forward the call to a fallback method. The library will tolerate failures up to a threshold. Beyond that, it leaves the circuit open. Which means, it will forward all subsequent calls to the fallback method, to prevent future failures. This creates a time buffer for the related service to recover from its failing state.

For a quick start following technologies stack being used:

  • Spring Boot 2.1.1.RELEASE
  • Spring 5.1.3.RELEASE
  • Hystrix 
  • Maven 3
  • JDK 1.8
  • Eclipse Oxygen

Project Structure

To demonstrate the circuit breaker design pattern we need a web service first. Name it ‘REST Producer’, because it provides data for the Hystrix-enabled ‘REST Consumer’


Module-1: Rest Producer

Dependency Management [pom.xml] 

<?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.1.1.RELEASE</version>
</parent>
<groupId>com.knowledgefactory</groupId>
<artifactId>springboot-rest-producer</artifactId>
<packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-rest-producer</name>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- spring mvc, rest -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

Controller

package com.knowledgefactory.knowledgefactorydemo;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Controller {
@RequestMapping(value = "/hello", method = RequestMethod.GET)
public ResponseEntity<String> listAllUsers() {
return new ResponseEntity<String>("Rest producer produced data", HttpStatus.OK);
}
}

Spring Boot

package com.knowledgefactory.knowledgefactorydemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

application.properties

server.port=9094

Module-2: Rest Consumer 

Maven/Dependency Management [pom.xml] 

<?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
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-rest-hystrix-consumer</artifactId>
<packaging>jar</packaging>
<name>spring-rest-hystrix-consumer</name>
<version>1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.1.RELEASE</version>
</parent>
<!-- Java 8 -->
<properties>
<java.version>1.8</java.version>
<downloadSources>true</downloadSources>
<downloadJavadocs>true</downloadJavadocs>
</properties>
<dependencies>
<!-- spring mvc, rest -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<!-- unit test rest -->
<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>Greenwich.RELEASE</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>
<groupId>com.knowledgefactory</groupId>
<url>www.knowledgefactory.net</url>
</project>

Controller

package com.knowledgefactory.knowledgefactorydemo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class Controller {
@Autowired
ServiceLayer service;

@RequestMapping(value = "/test", method = RequestMethod.GET)
public ResponseEntity<String> listAllUsers() {
return new ResponseEntity<String>(service.getService(), HttpStatus.OK);
}
}

Service 

package com.knowledgefactory.knowledgefactorydemo;

import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

@Service
public class ServiceLayer {
@HystrixCommand(fallbackMethod = "fallbackmethod")
public String getService() {
final String uri = "http://localhost:9094/hello";
RestTemplate restTemplate = new RestTemplate();
String result = restTemplate.getForObject(uri, String.class);
return result;
}

private String fallbackmethod() {
return "Service failed";
}
}

Spring Boot

package com.knowledgefactory.knowledgefactorydemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;

@SpringBootApplication
@EnableCircuitBreaker
public class KnowledgefactorydemoApplication {
public static void main(String[] args) {
SpringApplication.run(KnowledgefactorydemoApplication.class, args);
}
}

application.properties

server.port=9091

To see a Hystix circuit breaker in action we’re starting our ‘REST Consumer’ and pointing our browser to http://localhost:9091/test. Under normal circumstances, the following will be shown:

{Rest producer produced data}

To simulate a failure of our ‘REST Producer’, we’ll simply stop it, and after we finished refreshing the browser we should see a generic message, returned from the fallback method in our @Service:

{Service Failed}

Notes

The @EnableCircuitBreaker annotation will scan the classpath for any compatible Circuit Breaker implementation.
For the Circuit Breaker to work, Hystix will scan @Component or @Service annotated classes for @HystixCommand annotated methods, implement a proxy for it, and monitor its calls.

Popular posts from this blog

Spring boot video streaming example-HTML5

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Spring Boot + Mockito simple application with 100% code coverage

Spring Boot + OpenCSV Export Data to CSV Example

Custom Exception Handling in Quarkus REST API

DataTable-Pagination example with Spring boot, jQuery and ajax

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Node JS mini projects with source code - free download

Spring boot web project free download:User Registration System

Java - Blowfish Encryption and decryption Example