Spring Cloud Hystrix: resilient services

0. Índice de contenidos.

1. Introducción.

Hystrix es una librería que forma parte del stack de Spring Cloud, desarrollada por Netflix, que facilita la implementación del patrón circuit breaker dentro de una arquitectura de servicios distribuidos.

La comunicación entre sistemas adolece de indisponibilidades debidas a las propias características de los mismos: microcortes en las comunicaciones, servicio no disponible temporalmente, lentitud en las respuestas por el excesivo uso de un servicio,… el patrón circuit breaker permite gestionar estos problemas derivados de las comunicaciones estableciendo mecanismos de control, ayudando a mejorar la resiliencia de los sistemas.

De entre las características de hystrix podemos resaltar las siguientes:

  • ejecución de llamadas a sistemas externos o internos en segundo plano,
  • posibilidad de establecer timeouts en las peticiones,
  • posibilidad de establecer semáforos (pools de hilos), para cada petición, de forma que si no hay hilos disponibles la petición será rechazada en lugar de encolada,
  • proporciona métodos para gestionar la propagación de errores en cascada,
  • recolección de métricas de peticiones exitosas, fallidas y timeouts,
  • gestiona las llamadas para que, en caso de que un sistema externo exceda una cuota de errores definida, no se realicen más peticiones al mismo,
  • permite la declaración de fallbacks, en caso de error en una petición se ejecutará la estrategia definida para el caso de fallo,
  • proporciona un dashboard que integra las métricas capturadas,

En este tutorial veremos un ejemplo práctico de uso de hystrix para la gestión de fallbacks, integrado con clientes de feign.

2. Entorno.

El tutorial está escrito usando el siguiente entorno:

  • Hardware: Portátil MacBook Pro 15′ (2.5 GHz Intel Core i7, 16GB DDR3).
  • Sistema Operativo: Mac OS Sierra 10.12.5
  • Oracle Java: 1.8.0_25
  • Spring Cloud Dalston SR3

3. Ejemplo de definición de fallback.

Vamos a ver un ejemplo de interfaz de servicio:

Un cliente de feign sin ninguna particularidad especial:

Otro cliente de feign con una estrategia de fallback definida:

Apuntando a un cliente foo HelloWorldFooClient, que podría tener el siguiente código, para su ejecución por defecto en caso de error:

Si hacemos uso del cliente HelloWorldClient y no puede comunicarse con el servicio o este devuelve un error, se lanzará una HystrixRuntimeException:

Si bien, si hacemos uso del cliente HelloWorldFallBackClient y se produce un error en las comunicaciones, se invocará a la lógica del cliente alternativo HelloWorldFooClient, devolviendo la cadena “Bye “+ name + “!”

4. Ejecución de un test de integración.

Vamos a ejecutar un primer test de integración para comprobar que efectivamente el comportamiento del primer cliente es ese y, para ello, lo primero será exponer el código del test:

Sus características:

  • levanta un contexto de Spring Web con una serie de propiedades que ya vimos para feign, por un puerto random,
  • dentro del propio test declaramos un controlador que implementa la misma interfaz que los clientes que ya hemos visto,
  • habilitamos el cliente de feign que usaremos primero
  • en la configuración del controlador habilitamos un cliente de ribbon con una política de balanceo con un único servidor local, que apunta al mismo puerto que el servicio publicado -el establecido con un random e inyectado con un @Value(“${local.server.port}”); con ello evitamos tener que levantar cualquier otro tipo de infraestructura en local para las pruebas,
  • la lógica del controlador simplemente comprueba el parámetro de entrada para lanzar una excepción de Runtime o de negocio, aunque esta es también unchecked o devolver el resultado concatenando el parámetro de entrada,
  • por último, un par de métodos de test que comprueban tanto el positivo como el negativo y, este último, comprueba que se lanza una HystrixRuntimeException, que encapsula el mensaje de la excepción que lo origina.

Partiendo del test anterior vamos a extender la propia clase de test sobrescribiendo el segundo de los métodos (aunque no cuadre el nombre con su nueva lógica) y haciendo uso del segundo de nuestros clientes, el que sí contiene la estrategia de fallback, lanzamos el test:

Pese al nombre del método, ahora ya no se lanza la excepcíon puesto que hemos definido la estrategia de fallback; lo podemos comprobar en la salida por consola:

5. Configuración

Ejecutando el test con el nivel de logging a TRACE podemos ver todas las propiedades que se pueden establecer para configurar todas las estrategias de circuit braker, tanto a nivel del comando de hystrix (declaración de fallback en el cliente de feign) como a nivel global:

6. Referencias.

7. Conclusiones.

Continuamos examinando las posibilidades del stack de Spring Cloud.

Un saludo.

Jose