Guía de uso de Sentinel

Nombre

Uso de Sentinel

ID

A.ARQ.04

Versión

v 1.0.0

Licencia

Free

Área

Arquitectura

Fase

Lanzamiento

Tipo

Guía

Impacto

8 horas

 

Funcionalidad 

Guía para la configuración de Sentinel como Circuit breaker de nuestros microservicios.

 

Requisitos

Tener instalado el Onesait Architecture Development Environment

¿Cómo lo implementamos?

Las dependencias para la implementación de Circuit breaker con Sentinel están incluídas en la librería de utilidades que se disponibiliza desde el Initializr.

No obstante si se tiene que hacer una configuración directa se tendría que añadir en nuestro proyecto Spring Boot las siguientes dependencias:

pom.xml

<dependency>

<groupId>com.alibaba.csp</groupId>

<artifactId>sentinel-core</artifactId>

<version>1.7.2</version>

</dependency>

<dependency>

<groupId>com.alibaba.csp</groupId>

<artifactId>sentinel-annotation-aspectj</artifactId>

<version>1.7.2</version>

</dependency>

<dependency>

<groupId>com.alibaba.csp</groupId>

<artifactId>sentinel-transport-simple-http</artifactId>

<version>1.7.2</version>

</dependency>

Una vez importadas hay que crear una clase de configuración dentro del proyecto:

CircuitBreakerConfiguration.java

@Configuration

public class CircuitBreakerConfiguration {

 

@Bean

public SentinelResourceAspect sentinelResourceAspect() {

initDegradeRule();

return new SentinelResourceAspect();

}

private static void initDegradeRule() {

List<DegradeRule> rules = new ArrayList<DegradeRule>();

DegradeRule rule = new DegradeRule();

 

// Se le asigna un recurso a la regla

rule.setResource("responseTimeExample");

 

// Se indica el tipo de caso de la regla, en este, tiempo de respuesta

// DEGRADE_GRADE_EXCEPTION_COUNT o DEGRADE_GRADE_EXCEPTION_RATIO

rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);

 

// Se le asigna el limite al tiempo de respuesta que puede tener el servicio,

// aparte se le asigna la ventana de tiempo sobre la que se contarán los errores

rule.setCount(1000);

rule.setTimeWindow(60000);

 

rules.add(rule);

DegradeRuleManager.loadRules(rules);

}

 

}

En esta clase se define el bean para el aspect de los recursos de Sentinel que vamos a definir para implementar el Circuit Breaker, asi como las reglas que vayamos a definir para las mismas.

En este caso se está definiendo una regla de tiempo de respuesta para el recurso "responseTimeExample", con un tiempo de respuesta máximo de 1s dentro de una ventana de tiempo de 1 minuto.

Para poder hacer uso de la regla creada debemos definir el recurso, en este caso vamos a indicar que uno de nuestros servicios va a ser el recurso "responseTimeExample":

CircuitBreakerServiceImpl.java

@Service

public class CircuitBreakerServiceImpl implements CircuitBreakerService {

private final static String RT_FALLBACK_ERROR = "CIRCUIT BREAK - responseTimeExampleFallback";

@Override

@SentinelResource(value = "responseTimeExample", fallback = "responseTimeExampleFallback", defaultFallback = "responseTimeExampleFallback")

public String responseTimeService() {

return doSomething();

}

 

 

public String responseTimeExampleFallback() {

log.warn(RT_FALLBACK_ERROR);

return RT_FALLBACK_ERROR;

}

}

Para poder definir nuestro servicio como un recurso es necesario usar la anotación @SentinelResource:

  • value: Indica el nombre del recurso. Tiene que ser el mismo que el que adjuntes en la regla creada en la configuración.

  • fallback: Indica el nombre del método a invocar cuando salte la regla y el servicio se bloquee.

  • defaultFallback: Indica el nombre del método usado como fallback universal. No debería aceptar ningun parámetro y ser compatible con el tipo del retorno del método original.

 

Adicionalmente, Sentinel generará un fichero de log donde podremos ver registros de las peticiones y de las excepciones de Sentinel (en nuestro caso, DegradeException hace referencia a la excepción que lanza el circuit breaker) que hayan saltado:

Registros:

app-pid-metrics.log.fecha.xx

Timestamp|Date|Resource|PRS|BRS|ERS|ES|ART

1590052120000|2020-05-21 11:08:40|exceptionRatioExample|2|0|2|2|2|0|0|0

1590052122000|2020-05-21 11:08:42|exceptionRatioExample|1|0|1|0|0|0|0|0

1590052124000|2020-05-21 11:08:44|exceptionRatioExample|1|0|1|1|0|0|0|0

1590052125000|2020-05-21 11:08:45|exceptionRatioExample|1|0|1|1|2|0|0|0

1590052127000|2020-05-21 11:08:47|exceptionRatioExample|1|0|1|0|0|0|0|0

1590052128000|2020-05-21 11:08:48|exceptionRatioExample|2|0|2|2|1|0|0|0

1590052129000|2020-05-21 11:08:49|exceptionRatioExample|2|0|2|2|0|0|0|0

1590052130000|2020-05-21 11:08:50|exceptionRatioExample|1|0|1|0|0|0|0|0

1590052132000|2020-05-21 11:08:52|exceptionRatioExample|3|0|3|3|0|0|0|0

1590052133000|2020-05-21 11:08:53|exceptionRatioExample|2|5|2|2|0|0|0|0

1590052135000|2020-05-21 11:08:55|exceptionRatioExample|0|1|0|0|0|0|0|0

PRS: Pass resource per second.

BRS: Blocked resource per second.

ERS: Exit resource per second.

ES: Exception per second.

ART: Average response time.

Excepciones Sentinel:

sentinel-block.log

Timestamp|Index|Resource|Exception, default, Origin|blockTimes, 0

2020-05-20 12:08:03|1|responseTimeExample,DegradeException,default,|1,0

2020-05-20 12:11:53|1|responseTimeExample,DegradeException,default,|5,0

2020-05-20 12:08:03|1|responseTimeExample,DegradeException,default,|1,0

2020-05-20 12:11:53|1|exceptionRatioExample,DegradeException,default,|5,0

2020-05-20 12:13:33|1|exceptionRatioExample,DegradeException,default,|2,0

2020-05-20 12:15:16|1|exceptionCountExample,DegradeException,default,|1,0


Proyecto de ejemplo

Para ver todo en funcionamiento se ha desarrollado un proyecto de ejemplo disponible en el Git.

Este proyecto implementa los tres diferentes métodos disponibles en Sentinel para implementar el Circuit Breaking: tiempo de respuesta, número de excepciones y ratio de excepciones.

Este proyecto cuenta con su propia API REST y cada uno de estos casos está separado en distintos controllers para facilitar su manejo:

  • /exception-count-example: Caso por número de excepciones.

  • /exception-ratio-example: Caso por ratio de excepciones.

  • /response-time-example: Caso por tiempo de respuesta.

Todos estos controllers cuentan con dos endpoints en su interior. Uno de ellos ejecutará la función sin salirse de la regla, lo que sería el funcionamiento deseado de nuestro programa, y el otro incumplirá la regla. Cada uno de estas reglas tiene una característica distinta para que llegue a actuar el circuit breaker:

  • /exception-count-example: El número de excepciones por minuto está limitado a 5. Habría que ejecutar el endpoint 6 veces para que el circuito se rompa.

  • /exception-ratio-example: El ratio de excepciones está limitado a 0.5 (A menor el número, mayor la restricción de errores). En el momento en el que se empiecen a recibir muchas peticiones rápidas que hagan saltar excepciones, el circuito se romperá. 

  • /response-time-example: El tiempo de respuesta está limitado a 1s en la regla, uno de los endpoints está diseñado para tardar 3s. Habría que ejecutar el endpoint 6 veces para que el circuito se rompa.