Implementación del Patrón Circuit Breaker con Spring Boot y Hystrix

Airplane in a Thunderstorm with Lightning

imagen extraída de: www.cimformacion.com

En este artículo les propongo unirnos al mundo de Fault Tolerance y Resiliency, para esto primero conceptualizaremos que son estos términos:

Fault Tolerance: es la propiedad que permite a un sistema continuar en estado operativo aún cuando alguno de sus componentes falle.

Resiliency: es un término que va de la mano con Fault Tolerance y en muchos espacios pueden encontrarlos como un solo concepto, pero de lo que se trata realmente es del cúmulo de fallos que un sistema puede soportar sin quedar inoperativo.

 Estos conceptos fueron extraídos principalmente de los cursos online impartidos en JavaBrain, canal de Youtube que les recomiendo para adentrarse en el mundo de los microservicios.  Explicado en que consisten estos términos queda claro la necesidad de implementarlos es nuestras arquitecturas basadas en microservicios, y la razón principal es que querramos o no, TODO PUEDE FALLAR, ACEPTALO. Manejar fallas que pueden tomar al sistema una considerable cantidad de tiempo en recuperarse, si es que incluso se recupera, puede significar una mejora extraordinaria en la estabilidad de los sistemas que implementamos. Muchas de estas posibles fallas son mencionadas a continuación.

  • El servicio A no puede comunicarse con el servicio B.
  • La base de datos no es accesible.
  • Su aplicación no puede conectarse al sistema de archivos.
  • El servidor está inactivo o no responde.
  • Demoras en los servicios.
  • Fallas de conección

Sabiendo ya lo que queremos lograr y lo que queremos evitar, solo nos resta saber, ¿ cómo lograrlo? Para enfrentar los problemas anteriores les propongo una solución de las muchas posibles , el uso del Patrón: Circuit Breaker abordado ya en un artículo de este blog que nos da un preámbulo de este patrón tan utilizado en soluciones tecnológicas  enfocadas en manejar filosofías como Fault Tolerance y Reciliency. Como ya abordamos su conceptualización en un artículo anterior, SALTEMOS AL CODIGO !!!!

La implementación que les propongo utiliza la siguiente base tecnológica:

El objetivo del ejercicio que les propongo se ilustra la imagen siguiente:

A grandes rasgos tenemos un sistema basado en una arquitectura donde se comunican un número de microservicios y se crea un mecanismo de respuesta(fallback) en el caso de que alguno de estos falle en responder a una petición. El primer consejo en este escenario es razonar como en presencia de un circuito eléctrico, en qué lugar queremos poner nuestra protección contra fallos, a quien no le ha salvado todos los equipos electrodomésticos de la casa un simple Breaker de circuito.

Para implementar este patrón en Spring Boot se deben añadir las siguientes dependencias en nuestro pom.xml:

 <parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.1.2.RELEASE</version>
</parent>
<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-actuator</artifactId>
</dependency>

Especifico la versión de spring-boot-starter-parent porque con versiones superiores encontré problemas de compatibilidad para visualizar el Hystrix Dashboard.

Instaladas las dependencias pasamos a nuestra clase Main y añadimos las siguientes anotaciones, @EnableCircuitBreaker y @EnableHystrixDashboard:

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker // para añadir hystrix
@EnableHystrixDashboard // para tener acceso al dashboard hystrix
public class Main {
@Bean
	@LoadBalanced
	public RestTemplate getresttemplate() {
		return new RestTemplate();
	}
	public static void main(String[] args) {
		SpringApplication.run(Main.class, args);
	}
}

Ya estamos listos para usar las bondades de Hystrix, ahora llega el momento en que debemos pensar, ¿ dónde insertar nuestro circuit breaker ? No abordaremos la arquitectura de todo el sistema porque no es el objetivo del artículo, puede ser descargada aquí, a grandes rasgos tenemos una clase controladora que consume un servicio para brindar un dato.

@RestController
@RequestMapping("/api")
public class MainController {
	@Autowired
	MoviesService moviesServices;
	@RequestMapping("/movies")
	public List<Movie> myMovies() {
		List<Movie> movies = moviesServices.getMovies();
		return movies;
	}
}

Podríamos en este caso implementar en esta clase la ruptura del circuito en caso de que la llamada al servicio falle, pero para lograr una arquitectura más granular hacemos la implementación en el servicio que contiene el método solicitado en este caso la clase controladora solicita mediante la inyección del servicio MoviesService el método getMovies().

Para implementar la ruptura del circuito en el servicio se añade en el método que se desea interceptar la anotación @HystrixCommand, que en este caso recibe como parámetro el método que cumplirá las funciones de fallback. En resumen, en nuestro ejemplo si falla la llamada al servicio http://services-movies/api/movies/, en su lugar se solicitan los resultados devueltos por getFallbackMovies().

@Service
public class MoviesService {
	@Autowired
	RestTemplate restTemplate;
  @HystrixCommand(fallbackMethod="getFallbackMovies")
  public List<Movie> getMovies(){
		ResponseEntity<Movie[]> response =
				  restTemplate.getForEntity(
				  "http://services-movies/api/movies/",
				  Movie[].class);
				Movie[] movies = response.getBody();
				List<Movie> m = Arrays.asList(movies);
		return  m;
	}
   public List<Movie> getFallbackMovies() {
	return Arrays.asList(new Movie(4, "Película suplente", "suplente"));
	}
}

Y esto es todo colegas, ya tenemos el patrón Circuit Breaker implementado en nuestra aplicación, si queremos llegar un poco más lejos podemos tener un dashboard con el estado del circuito, ya instalamos la dependencia de Spring Boot que se encarga de esto “spring-cloud-starter-netflix-hystrix-dashboard”, solo nos resta añadir en el application.properties la siguiente línea para hacer visible el endpoint de hystrix que maneja estos datos:

management.endpoints.web.exposure.include=hystrix.stream

Con este parámetro configurado accedemos a:

http://Localhost:port/hystrix

Insertamos la dirección de los datos recolectados por Hystrix:

http://localhost:port/actuator/hystrix.stream

Y si todo sale bien se logra el acceso al dasboard de Hystrix

Aquí está todo el código disponible para su descarga.

Algunas anotaciones importantes:

Netflix anunció que ya no implementará nuevas funcionalidades para el proyecto Hystrix, para el propósito del artículo es válido su uso, pero la recomendación es revisar Resilience4j, sobre este proyecto estaremos hablando en próximos artículos.

Espero que este artículo fuera útil para tí, nos leemos en el próximo!!!

1 thought on “Implementación del Patrón Circuit Breaker con Spring Boot y Hystrix

Comments are closed.