Nube de primavera: Hystrix

En este artículo, le presentaremos Spring Cloud Netflix Hystrix. Es una biblioteca de tolerancia a fallas, que implementa el patrón empresarial Circuit Breaker...

Visión general

En este artículo, te presentaremos Nube de primavera Netflix Hystrix. Es una biblioteca de tolerancia a fallas, que implementa el patrón empresarial Cortacircuitos, un patrón diseñado para evitar fallas en cascada.

En una arquitectura de microservicio típica, tenemos muchas aplicaciones pequeñas que se ejecutan por separado. Es bastante común que un servicio llame a otro servicio (puede haber más de uno) para completar una solicitud en particular. Siempre existe la posibilidad de que uno de estos servicios posteriores no responda correctamente o simplemente falle por completo.

Un solo bloqueo puede dar lugar a fallas en cascada que conducen a demasiadas llamadas de red fallidas, desperdicio de memoria y hace que el servicio superior que realmente recibió la solicitud sea lento.

El principio del patrón del disyuntor es análogo al de la electrónica:

Hay disyuntores en nuestras casas que vigilan cualquier falla. Cuando ocurre una falla, abre el circuito (desconectando el circuito) y así aísla el área fallada. Una vez que haya solucionado el problema, puede cerrar manualmente el circuito accionando el interruptor. Esto evita que su casa se queme.

De la misma manera, Hystrix está observando los métodos para fallar en las llamadas a los servicios de descarga. Si una llamada de servicio descendente falla con más frecuencia de lo permitido, Hystrix "abrirá el circuito", aislando las llamadas a ese servicio.

Podemos agregar un método alternativo que se llamará si el circuito está abierto, lo que nos permite recuperar la aplicación del estado de falla. Hystrix cierra automáticamente el circuito después de un cierto tiempo, lo que le da tiempo al servicio descendente que falla para recuperarse.

Configuración

En este artículo se supone que ya tiene conocimiento del Proyecto Eureka de Netflix, que se usa como un registro de servicios y para equilibrar la carga. . . .

Así es como se ve nuestro servicio de back-end:

  • Servidor Eureka: Actúa como un registro de servicios y se ejecuta en el puerto 8761.
  • Servicio de recomendación: un servicio REST simple que tiene un punto final único de /recomendaciones y se ejecuta en el puerto 8070.
  • Servicio de usuario: un servicio REST simple que tiene un punto final único de /personalizado/{id} y se ejecuta en el puerto 8060.

El servicio de usuario llama internamente al servicio de recomendación para obtener el resultado de /personalizado/{id}:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
@RestController
public class UserRestController {

    @Autowired
    RestTemplate restTemplate;

    @GetMapping(value = "/personalized/{id}")
    public Product[] personalized(@PathVariable int id) {
        Product[] result = restTemplate.getForObject("http://recommendation-service/recommendations", Product[].class);
        return result;
    }
}

Comencemos todos los servicios, navegue su navegador al servidor Eureka en http://localhost:8761/:

configuración-primavera-nube-hystrix

Ahora, probemos el punto final del servicio de usuario navegando el navegador hasta el punto final http://localhost:8060/personalizado/1:

spring-cloud-hystrix-user-service-result-success

Ahora, solo para ver qué sucede, detenga recommendation-service y vuelva a presionar el punto final anterior:

spring-cloud-hystrix-user-service-result-failuer

Entonces obtuvimos una respuesta de error 500, y esto puede cambiar dependiendo de la implementación.

Sería malo que esto sucediera cuando un usuario final confía en nuestra aplicación. ¿Y si otro servicio también estuviera esperando una respuesta?

Para evitar estas situaciones, avancemos e implementemos Hystrix en nuestra aplicación.

Adición de Hystrix

Para agregar Hystrix a nuestro servicio de usuario, necesitamos importar la dependencia apropiada en nuestro pom.xml:

1
2
3
4
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

En el caso de que esté creando un proyecto desde cero, puede seleccionar esta dependencia desde Spring Initializr:

spring-cloud-hystrix-spring-intializr

Para habilitar Hystrix, debemos anotar nuestra clase principal con @EnableCircuitBreaker o @EnableHystrix. La primera opción nos permite implementar el patrón de interruptor automático también con otras tecnologías. Esta última opción nos permite implementar el patrón de interruptor automático solo con Hystrix:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public class Application {

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

    @LoadBalanced
    @Bean
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

Ahora, queremos buscar lugares adecuados para implementar el patrón del disyuntor. Una vez que encontremos un punto que podría fallar y donde queremos romper el circuito si es necesario, lo anotaremos con @HystrixCommand.

Esto envuelve un método potencialmente riesgoso y nos permite definir un respaldo y un punto de interrupción para él, usando el atributo fallbackMethod.

Agreguemos esto a nuestro método .personalizado():

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@GetMapping(value = "/personalized/{id}")
@HystrixCommand(fallbackMethod = "recommendationFallback")
public Product[] personalized(@PathVariable int id) {
    Product[] result = restTemplate.getForObject("http://recommendation-service/recommendations", Product[].class);
    return result;
}

public Product[] recommendationFallback(int id) {
    System.out.println("=======recommendationFallback=========" + id);
    return new Product[0];
}

En la anotación @HystrixCommand, agregamos un atributo de fallbackMethod, que apunta al método alternativo que queremos ejecutar. Este atributo tiene que coincidir exactamente con nuestro nombre de método, por supuesto.

Tenga en cuenta que el tipo de valor devuelto y el parámetro del método alternativo son los mismos que los del método original. Esto se debe a que el método alternativo debe tener la misma firma que el original. Aunque, en lugar de devolver datos reales, solo devolvemos una matriz vacía.

Reconstruyamos y comencemos el servicio de usuario nuevamente. Funcionará igual que antes cuando el servicio de recomendación esté activo.

Pero si detenemos el ‘servicio de recomendación’ y volvemos a presionar el punto final ‘/personalizado/{id}’ del servicio de usuario, obtendremos un mensaje muy diferente:

spring-cloud-hystrix-user-service-fallback

Para configurar el @HystrixCommand puedes usar el atributo comandoPropiedades con una lista de @HystrixProperty anotaciones.

Tablero Hystrix

Hystrix también proporciona una función opcional para monitorear todos sus interruptores automáticos de una manera visualmente amigable.

Vamos a crear un nuevo proyecto para este tablero. Como siempre, la mejor manera de comenzar con un proyecto básico es usar Spring Initializr.

Seleccione su versión preferida de Spring Boot y agregue la dependencia "Hystrix Dashboard", y genere como un proyecto Maven:

spring-cloud-hystrix-spring-intializer-hystrix-dashboard

Para habilitarlo, debemos agregar la anotación @EnableHystrixDashboard a nuestra clase principal:

1
2
3
4
5
6
7
@SpringBootApplication
@EnableHystrixDashboard
public class HystrixDashboardApplication {
    public static void main(String[] args) {
        SpringApplication.run(HystrixDashboardApplication.class, args);
    }
}

Iniciemos este servicio en el puerto 9903 y naveguemos nuestro navegador hasta el punto final http://hostlocal:9903/hystrix:

spring-cloud-hystrix-dashboard-ui

Adición del flujo de métricas de Hystrix

Para poder usar el tablero de Hystrix, nuestros microservicios habilitados para respaldo deben proporcionar datos al tablero a través de Hystrix Metrics Stream.

Para agregar esto en nuestro servicio de usuario, debemos incluir la dependencia actuador en nuestro proyecto:

1
2
3
4
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Además, en su application.properties incluyamos la secuencia:

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

Al hacerlo, expone /actuator/hystrix.stream como un punto final de administración.

Monitoreo de un flujo de Hystrix

Necesitamos monitorear el flujo de métricas de Hystrix del servicio de usuario. Para eso, escriba http://localhost:8060/actuator/hystrix.stream en el cuadro y haga clic en "Monitor Stream".

spring-cloud-hystrix-dashboard-ui

Puede ver muchas métricas relacionadas con el punto de conexión del servicio de usuario a través de esta transmisión.

El monitoreo de muchas aplicaciones habilitadas para Hystrix podría ser un desafío, por lo que Spring proporcionó otro proyecto llamado [Turbina] (https://github.com/spring-cloud/spring-cloud-netflix/tree/master/spring-cloud-netflix-turbine) , que agregará flujos para presentarlos en un Tablero Hystrix.

Conclusión

En este artículo, hemos cubierto cómo usar el mecanismo de reserva de Hystrix en nuestros microservicios para evitar fallas en cascada. También configuramos Hystrix Metrics Streams en Hystrix Dashboard para monitorear las métricas de nuestros puntos finales.

Como siempre, el código de los ejemplos utilizados en este artículo se puede encontrar en Github.