BLOG

Programación-Tecnología

La comunicación entre sistemas mediante llamadas remotas es un procedimiento muy habitual hoy en día. Este tipo de comunicaciones, si cabe, cobra aun más relevancia en sistemas basados en arquitecturas orientadas a microservicios.

El problema de las comunicaciones remotas es que pueden fallar (servicios caídos, demasiados consumidores realizando peticiones generando mayor lentitud en las respuestas, etc). Patrones de diseño como Circuit Breaker permiten establecer un mecanismo de control y gestión de los problemas derivados de la comunicación remota, ayudando, por tanto, a mejorar la resiliencia de los sistemas.

¿Qué es Hystrix?

Se trata de una librería ofrecida por Netflix diseñada para aislar puntos de acceso a sistemas remotos, servicios y librerías de terceros, deteniendo fallos en cascada y permitiendo mejorar la resiliencia en sistemas complejos distribuidos donde la probabilidad de fallo es inevitable.

El siguiente diagrama de estados muestra como un sistema resiliente funciona durante el ciclo de vida del circuit breaker

Diagrama de estados Circuit Breaker

Si el sistema funciona con normalidad, el circuit breaker permanecerá cerrado (estado closed). En el caso de comenzar a ser inestable y se alcance un limite de fallos, el circuito se abrirá para prevenir más errores (estado open). Cada cierto intervalo de tiempo, se pasa al estado half open donde Hystrix se encarga de enviar una primera petición para comprobar la disponibilidad del sistema, pasando de nuevo al estado closed (si el funcionamiento vuelve a ser el correcto) u open (si la inestabilidad del sistema continua).

Antes de empezar

En el post anterior vimos como construir microservicios con Spring Boot donde se explicaba paso a paso cómo implementar un Hola Mundo con microservicios spring boot, haciendo uso de Eureka como servidor de registro y descubrimiento.
ejemplo practico

Partiendo del ejemplo anterior, lo siguiente que veremos será un ejemplo sobre cómo implementar un circuit breaker con hystrix. Puedes descargarte el código completo de este ejemplo desde mi proyecto de GitHub aquí.

Paso 1: Añadir Hystrix al proyecto

Lo primero de todo será incluir Hystrix como una nueva dependencia en el fichero pom.xml del microservicio client-greeting.

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

Paso 2: Aplicar Circuit Breaker Pattern

Spring Cloud Netflix Hystrix buscará cualquier método con la anotación @HystrixCommand, el cual envolverá en un proxy conectado al circuit breaker para que Hystrix pueda monitorizarlo. Estos métodos deberán pertenecer a una clase anotada necesariamente con @Component o @Service

@Service
public class ClientGreetingService {
	
	@HystrixCommand(fallbackMethod = "greetingDefault")
	public Greeting greeting (String name) {	
		
		return restTemplate.getForObject(serviceUrl + "/greeting/{name}",Greeting.class, name);		
	}
	
	public Greeting greetingDefault(String name) {
	    return new Greeting("Hello World thanks to Circuit Breaker (Hystrix)");
	 }
}

Observa que en la anotación @HystrixCommand se especifica el fallbackMethod, atributo donde se indica a Hystrix que método llamar al abrirse el circuit breaker en el caso de que surgieran problemas en la llamada remota REST al microservicio greeting.

Para que Hystrix localice correctamente el método de fallback, es importante que éste se encuentre ubicado en la misma clase que el método anotado con @HystrixCommand con el que está asociado y que la signatura de ambos sea la misma (sólo cambia el nombre del método)

El ejemplo anterior muestra el modelo sincrono de Hystrix pero ten en cuenta que existen otros dos modelos de ejecución:

  • Asíncrona (Future): Realiza el control de ruptura del circuito en modo asíncrono
@HystrixCommand(fallbackMethod = "greetingFutureDefault")
public Future&lt;Greeting&gt; greetingFuture(final String name) {
	return new AsyncResult&lt;Greeting&gt;() {
	public Greeting invoke() {
		return restTemplate.getForObject(serviceUrl + "/greeting/{name}", Greeting.class, name);
	}
	}; 		
}
  • Reactiva (Observable): Declara un método como callback, pudiendo definir varios comportamientos dependiendo del resultado de la llamada (casos de éxito, error, etc). Funciona como un modelo de subscripción a una cola de respuesta. Por el momento, y para no hacer más complejo el ejemplo, dejaremos la implementación de este caso para más adelante

 Paso 3: Habilitar Circuit Breaker

Incluir la anotación @EnableCircuitBreaker para indicar a Spring Cloud que el microservicio client-greeting utiliza circuit breaker y habilitar la monitorización, apertura y cierre del circuito

@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class ClientGreetingServer {

	public static void main(String[] args) {
		// Tell server to look for web-server.properties or web-server.yml		
		SpringApplication.run(ClientGreetingServer.class, args);
	}
	...
}

Paso 4: Probar Circuit Breaker

  1. Inicia Eureka. Accede a https://localhost:1111 y comprueba que visualizas correctamente el dashboard del servicio de registro
  2. Levanta el microservicio greeting (GreetingServer). Comprueba que el microservicio se registra correctamente en Eureka y que responde a peticiones REST como la siguiente: https://localhost:2222//greeting/Rob
  3. Ejecuta el microservicio client-greeting (ClientGreetingServer). Al igual que en el caso anterior, verifica que aparece registrado en Eureka y que está accesible en https://localhost:3333

Greeting-Client-Service

Si pinchas en el link Fetch by Name, el microservicio client-greeting-service llamará a Eureka para localizar el endpoint del microservicio greeting-service y a continuación realizará una petición REST para llamar al método greeting de este servicio pasándole como parámetro un nombre (“Rob”). A continuación muestro el resultado

REST Greeting-Service

 

4. Para probar el circuit breaker vamos a simular que el microservicio greeting no responde correctamente a las peticiones. Para ello vamos a detener su ejecución. A continuación sitúate de nuevo en la página principal del microservicio client-greeting (https://localhost:3333) y vuelve a ejecutar la operación Fetch by Name. En esta ocasión, al encontrarse el microservicio greeting caído y por tanto no responder a la peticiones recibidas, Hystrix detectará el error, abrirá el circuit breaker y derivará el flujo de la ejecución al método greetingDefault(String name) que devolverá un mensaje de saludo genérico como el que se muestra a continuación:
resultado circuit breaker

Espero te haya resultado interesante esta entrada y te animo a utilizar este patrón en los casos de uso que te resulten más apropiados.

Referencias

Comparte este artículo si te gustó:

2 Responses

  1. Hola Roberto:

    Primero que nada felicitarte por el tuto, soy nuevo en microservicios y he investigado bastante y es el primer ejemplo que encuentro en español.

    Tengo una duda, tal vez tu puedas orientarme, quiero implementar el patrón Api Gateway utilizando Zuul, pero necesito utilizar service composite y no he podido encontrar como orquestar servicios aplicando los filtros que ofrece Zuul, sabrás algo al respecto??

    Muchas gracias de antemano. Saludos!!

    • Hola Marco

      Lo primero de todo agradecerte tu comentario. Justamente la falta de información sobre microservicios en castellano fue una de las razones por las que me animé a realizar esta serie de posts.
      En cuanto a la duda que me planteas, no sé si esta guía puede servirte de ayuda: https://kubecloud.io/apigatewaypattern/. Tomo nota de este tema para investigar más al respecto y valorar la posibilidad de realizar en el futuro un artículo que ayude a resolver problemáticas como las que planteas

      Saludos!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.