probando spring netflix – parte 6 ( Hystrix + turbine)

Qué es Hystrix

Hystrix es una librería creada para mejorar el comportamiento de un sistema de servicios distribuidos ante caídas de algunos de los servicios del mismo.

Propósito de Hystrix

  • Dar protección y control sobre la latencia y fallos por accesos en librerías de terceras partes
  • Evitar los fallos en cascada en sistemas distribuidos
  • Fallar rápido y recuperación veloz.
  • Fallback y gracefully degrade siempre que sea posible.
  • Permitir monitorización casi en tiempo real, alertas y control operacional

Es sencillo de usar. Para ello añadimos la dependencia maven a nuestra aplicación cliente

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

a continuación marcamos el método que queremos proteger con la anotación

@HystrixCommand

usando su propiedad fallbackMethod para indicar a qué método llamar en el caso de que la llamada inicial falle. Por lo tanto cambiamos nuestro controlador para soportar este comportamiento de la siguiente forma:

Creamos una clase que nos proporcione la frase:

@Component
public class PhraseRetriever {

	@Autowired
	private StringClient stringClient;

	@HystrixCommand(fallbackMethod=&quot;retrieveFallbackGeoinfo&quot;)
	public String geoInfo() {
		return stringClient.geoinfo();
	}

	@HystrixCommand(fallbackMethod=&quot;retrieveFallbackHome&quot;)
	public String home() {
		return stringClient.home();
	}

	public String retrieveFallbackGeoinfo() {
		return "Madrid";
	}

	public String retrieveFallbackHome() {
		return "hi fellas!";
	}
}

Es importante no poner commands de hystrix a nivel de controlador, ya que los proxies entran en conflicto y no funciona.

La incluimos en el controlador

@RestController
public class RestHomeController {

	@Autowired
	private PhraseRetriever phraseRetriever;

	@RequestMapping("/")
	public String printPhrase() {
		 String results = phraseRetriever.home() + " I'm at " + phraseRetriever.geoInfo();
       return results;
	}
}

y por último, a la clase principal de nuestro aplicación la marcamos con la anotación
@EnableCircuitBreaker

@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableDiscoveryClient
@EnableCircuitBreaker
@FeignClientScan
public class AppClient
{

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

De esta forma, si arrancamos todo, obtendremos:

Hello World! with alias people I'm at latitud:2,23234 longitud:45.3222

si paramos el microservicio string, pasamos a obtener:

hi fellas! I'm at latitud:2,23234 longitud:45.3222

con lo que podemos ver que el fallback ha entrado en acción.

modelos de control de ruptura Hystrix

Hystrix proporciona tres modelos para controlar las rupturas de comunicación en los sistemas que gestiona:

Hystrix Síncrono

Este modelo realiza el control de ruptura del circuito de comunicación de modo asíncrono. Es el que hemos visto previamente:

private String getDefaultMessage() {
  return "Hello World Default";
}

@HystrixCommand(fallbackMethod="getDefaultMessage")
public String getMessage() {
  return restTemplate.getForObject(/*...*/);
}

Hystrix futuro

Este modelo realiza el control de ruptura del circuito de comunicación de modo asíncrono:

@HystrixCommand(fallbackMethod="getDefaultMessage")
public Future<String> getMessageFuture() {
  return new AsyncResult<String>() {
    public String invoke() {
      return restTemplate.getForObject(/*...*/);
    }
  };
}

//somewhere else
service.getMessageFuture().get();

Hystrix observable

Este método declara un método como callback, pudiendo definir varios comportamientos dependiendo del resultado de la llamada como pueden ser los casos de éxito, error … Funciona como un modelo de subscripción a una cola de respuesta.

@HystrixCommand(fallbackMethod="getDefaultMessage")
public Observable<String> getMessageRx() {
  return new ObservableResult<String>() {
    public String invoke() {
      return restTemplate.getForObject(/*...*/);
    }
  };
}

//somewhere else
helloService.getMessageRx().subscribe(new Observer<String>() {
    @Override public void onCompleted() {}
    @Override public void onError(Throwable e) {}
    @Override public void onNext(String s) {}
});

exponemos aquí el diagrama de flujo de su comportamiento:

hystrix-command-flow-chart

 

la manera de ejecutar los comandos de Hystrix para realizar la llamada al destino son 4:

  • execute() — realiza bloqueo en la ejecución, y devuelve la respuesta recibida de la dependencia (o lanza una Excepción en caso de error). Es el modelo asíncrono.
  • queue() — devuelve un objeto Future, con el cual se puede obtener la respuesta desde la dependencia. Es el que usa el modelo asíncrono.
  • observe() — se subscribe a un objeto Observable que representa la(s) respuesta(s) desde la dependencia y devuelve un objeto Observable que replica el del origen. Es el que usa el modelo observable.
  • toObservable() — devuelve un objeto Observable que, cuando te subscribes a él, ejecutará el comando Hystrix y emitirá su respuesta

Realmente el modelo síncrono ejecuta execute() el cual por dentro ejecuta queue().get()queue() a su vez invocavtoObservable().toBlocking().toFuture(). Por lo que podemos observar que todo comando  HystrixCommand acaba realizando una implementación Observable.

caché

Por defecto Hystrix cachea las llamadas que realiza devolviendo el objeto Observable. Si no se quiere este comportamiento habría que deshabilitar la caché.

métricas

  • Se pueden consultar via actuator /metrics
  • Los eventos de servidor se pueden consultar mediante el stream /hystrix.stream

Para saber más sobre cómo funciona Hystrix os recomiendo leer su documentación.

Hystrix Dashboard

Podemos enriquecer la monitorización de nuestros circuitos de servicios mediante el dashboard de hystrix.

Lo ideal es crear una aplicación ajena a los servicios para este hito, ya que así no perdemos la monitorización en el el caso de que el servicio se caiga.

Para ello creamos una aplicación maven y la hacemos “bootable”.

Añadimos la dependencia maven:

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

A continuación, a la clase principal de la aplicación la marcamos con la anotación:

@EnableHystrixDashboard

y arrancamos. Accedemos a la página principal de la misma con la uri /hystrix, es decir, en nuestro caso http://localhost:9000/hystrix y debemos ver el dashboard.

Captura de pantalla 2015-01-06 a las 0.09.59

añadimos la información del servicio a monitorizar, en nuestro caso http://localhost:9100/hystrix.stream y voalá, comenzaremos a ver su monitorización:

Captura de pantalla 2015-01-06 a las 0.09.16

turbine

Para poder “clusterizar” todas las monitorizaciones hystrix en un único punto de monitorización podemos usar turbine. Turbine usa Eureka para registrar cada punto de monitorización en el sistema mediante la anotación

@EnableTurbine

Para poder usarlo en nuestros microservicios, en primer lugar añadimos la dependencia maven a nuestro proyecto hystrixdashboard:

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-netflix-turbine</artifactId>
</dependency>

A continuación añadimos la anotación a la clase principal de nuestro dashboard:

@Configuration
@EnableAutoConfiguration
@EnableHystrixDashboard
@ComponentScan
@EnableTurbine
public class HeystrixDashboardApp
{
    public static void main( String[] args )
    {
    	new SpringApplicationBuilder(HeystrixDashboardApp.class).web(true).run(args);
    }
}

A nivel de configuración vamos a definir dos propiedades útiles para turbine:

  • turbine.appConfig es una lista de servicios Eureka que deben exponer su monitorización.
  • turbine.aggregator.clusterConfig se usa para agrupar los servicios expuestos en clusters. Debe estar en mayúsculas y coincidir con el nombre de los servicios expuestos en appConfig, tal y como explica la siguiente nota.

Sabiendo esto, añadimos la configuración necesaria en nuestro application.yml:

turbine:
  aggregator:
    clusterConfig: MICROSERVICESCLIENT
  appConfig: microservicesclient

y ya tenemos nuestro cluster turbine para monitorizar nuestros microservicios.

ahora solo tenemos que indicar

http://turbine-hostname:port/turbine.stream?cluster=%5BclusterName%5D, que en nuestro caso es http://localhost:9000/turbine.stream?cluster= MICROSERVICESCLIENT

y veremos el cluster:

Captura de pantalla 2015-03-12 a las 9.18.46

veamos por donde vamos y cual es el siguiente paso, como siempre en rojo:

  • Configuración distribuida
  • Registro y autoreconocimiento de servicios
  • Enrutado
  • Llamadas servicio a servicio
  • balance de carga
  • Control de ruptura de comunicación con los servicios
  • mensajería distribuida

veamos en el siguiente post como montar un bus para la configuración de todo nuestro sistema a través de rabbitMQ.

Esta entrada fue publicada en cloud, java, microservices, spring y etiquetada , , , , , . Guarda el enlace permanente.

3 respuestas a probando spring netflix – parte 6 ( Hystrix + turbine)

  1. Roland Cruz dijo:

    Hola, muy buenos tus tutoriales. Sin embargo tengo un problema y no se a que se deba…
    Tengo un esquema similar, pero con la diferencia que manejo sesiones compartidas usando REDIS. Todo funciona muy bien, pero no he encontrado la forma de enviar la informacion de autenticación cuando quiero acceder un servicio que encuentra asegurado. Te agradezco si me puedes orientar al respecto

  2. Pingback: Cómo construir microservicios con Spring Boot (V) – Turbine -Roberto Crespo

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión /  Cambiar )

Google photo

Estás comentando usando tu cuenta de Google. Cerrar sesión /  Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión /  Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión /  Cambiar )

Conectando a %s