Resumen de aprendizaje de Hystrix

Articulo de referencia

Fusión y degradación del servicio de Hystrix

Fusión y degradación de servicios (Hystrix)

SpringCloud (6) -Fuse comprensión de degradación, combate real de Hystrix

Vernáculo: la diferencia entre la degradación del servicio y el disyuntor

Tolerancia a fallas del servicio Spring Cloud Hystrix

Panel de control Spring Cloud Hystrix

Principio de Hystrix y combate real (el artículo es un poco más largo)

Fusible Hystrix VS degradación

La degradación del fusible es un mecanismo de protección del enlace de microservicio para hacer frente al efecto de avalancha. Cuando un microservicio del enlace de distribución no está disponible o el tiempo de respuesta es demasiado largo, el servicio se degradará y, a continuación, se cancelará la llamada al microservicio del nodo. fusible, y devuelva rápidamente la información correspondiente del error.

Similitudes :

El mismo objetivo es partir de la disponibilidad y la confiabilidad, para evitar que el sistema falle;

La experiencia del usuario es similar, lo que en última instancia hace que la experiencia del usuario sea que algunas funciones no están disponibles temporalmente;

Diferencia :

Downgrade: al acceder a un servicio de bajada, si hay un tiempo de espera, tiempos de falla, falla o límite actual, acceda al método especificado por Hystrix, regrese rápidamente a la información de respaldo y realice la operación de downgrade.

Fusible: si hay demasiados errores al acceder a un servicio downstream, se supera el umbral. Luego, la llamada de servicio se fusionará directamente y la información en espera se devolverá directamente sin llamar al servicio la próxima vez. Ambas fusiones son una degradación calificada.

Hystrix proporciona los siguientes parámetros clave para configurar un fusible:

circuitBreaker.requestVolumeThreshold    //滑动窗口的大小,默认为20 
circuitBreaker.sleepWindowInMilliseconds //过多长时间,熔断器再次检测是否开启,默认为5000,即5s钟 
circuitBreaker.errorThresholdPercentage  //错误率,默认50%

Poniendo los 3 parámetros juntos, el significado es:

Siempre que falle el 50% de las 20 solicitudes, se abrirá el fusible, si se vuelve a llamar al servicio en este momento, se devolverá directamente el fallo y no se llamará al servicio remoto. Hasta 5 segundos después, vuelva a verificar la condición del gatillo para determinar si cerrar el fusible o continuar abriendo.

Instancia de Hystrix

1. Introduzca el frasco

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

2. Agregue @EnableCircuitBreaker a la clase de entrada

@EnableCircuitBreaker
@EnableDiscoveryClient
@SpringBootApplication
public class DemoApplication {
    
    
    @Bean
    @LoadBalanced
    RestTemplate restTemplate() {
    
    
        return new RestTemplate();
    }
    public static void main(String[] args) {
    
    
        SpringApplication.run(DemoApplication.class, args);
    }
}

También puede agregar @EnableHystrix. @EnableHystrix y @EnableCircuitBreaker son equivalentes.

3 、 @HystrixCommand

@HystrixCommand(fallbackMethod = "getUserDefault")
public User getUser(@PathVariable Long id) {
    
    
   return restTemplate.getForObject("http://Server-Provider/user/{id}", User.class, id);
}

public User getUserDefault(Long id) {
    
    
    User user = new User();
    user.setId(-1L);
    user.setUsername("defaultUser");
    user.setPassword("123456");
    return user;
}

Agregamos la anotación @HystrixCommand al método getUser. El atributo fallbackMethod de la anotación especifica el método de devolución de llamada cuando el método llamado no está disponible (lógica de procesamiento de devolución de llamada cuando el servicio está roto, es decir, degradación del servicio), aquí está el método getUserDefault ( debe ser con el método getUser Los parámetros y los tipos de valor de retorno son los mismos).

Notas comunes de Hystrix

HystrixCommand

Atributos Descripción Muestra
fallbackMethod Especifique el método de devolución de llamada cuando el método llamado no esté disponible fallbackMethod = "getUserDefault"
ignoreExceptions Especificar que una excepción no desencadena la degradación del servicio ignoreExceptions = {NullPointerException.class}
commandKey El nombre del comando commandKey = "getUserById"
groupKey Nombre del grupo groupKey = "userGroup"
threadPoolKey Nombre del grupo de subprocesos threadPoolKey = "getUserThread"

Para la información de excepción lanzada por el método, podemos usar el objeto Throwable en el método de degradación del servicio para obtener

@HystrixCommand(fallbackMethod = "getUserDefault",commandKey = "getUserById", groupKey = "userGroup",
        threadPoolKey = "getUserThread" , ignoreExceptions = {
    
    NullPointerException.class})
public User getUser(@PathVariable Long id) {
    
    
	//代码省略
}

public User getUserDefault(Long id, Throwable e) {
    
    
    //代码省略
}

La configuración anterior especifica el nombre del comando como getUserById, el nombre del grupo como userGroup y el nombre del grupo de subprocesos como getUserThread.

Al configurar el grupo de comando, Hystrix organizará y contará las alarmas de comando, los paneles de control y otra información de acuerdo con el grupo. De forma predeterminada, el comando Hystrix divide el grupo de subprocesos por nombre de grupo, es decir, los comandos con el mismo nombre de grupo se colocan en el mismo grupo de subprocesos. Si el nombre del grupo de subprocesos lo establece threadPoolKey, se divide según el nombre del grupo de subprocesos .

Cuando se llama al método getUser, el registro se imprime de la siguiente manera:

2018-06-06 15:32:55.945  INFO 16192 --- [getUserThread-1] com.example.demo.Service.UserService  : 获取用户信息

Puede ver que el nombre del hilo es getUserThread-1.

Caché de Hystrix

1. Agregar filtro.

De hecho, la caché de Hystrix todavía es bastante insípida, la caché de solicitudes no solo se escribe una vez y el resultado no cambiará, sino que cada vez que llega una solicitud al controlador, necesitamos inicializar HystrixRequestContext, y la caché anterior simplemente no lo hace. existen. Garantizamos el mismo resultado en la misma solicitud. El resultado se almacena en caché después del primer acceso en la misma solicitud. ¡ El ciclo de vida de la caché es solo una solicitud !

@Component
@WebFilter(filterName = "hystrixRequestContextServletFilter", urlPatterns = "/*", asyncSupported = true)
public class HystrixRequestContextServletFilter implements Filter {
    
    
    @Override
    public void init(FilterConfig filterConfig) {
    
    
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
    
    
        HystrixRequestContext context = HystrixRequestContext.initializeContext();
        filterChain.doFilter(servletRequest, servletResponse);
        context.close();
    }

    @Override
    public void destroy() {
    
    
    }
}

2. Agregue @CacheResult, especifique la clave y especifique la clave de las siguientes maneras:

a. Especifique la clave mediante la anotación @CacheKey

@CacheResult
@HystrixCommand(fallbackMethod = "getUserDefault", commandKey = "getUserById", groupKey = "userGroup",
        threadPoolKey = "getUserThread")
public User getUser(@CacheKey("id") @PathVariable Long id) {
    
    
    log.info("获取用户信息");
    return restTemplate.getForObject("http://Server-Provider/user/{id}", User.class, id);
}

b. Especifique por el método, el valor de retorno del método debe ser de tipo String

public String getCacheKey(Long id) {
    
    
    return String.valueOf(id);
}

@CacheResult(cacheKeyMethod = "getCacheKey")
@HystrixCommand(fallbackMethod = "getUserDefault", commandKey = "getUserById", groupKey = "userGroup",
        threadPoolKey = "getUserThread")
public User getUser(Long id) {
    
    
    log.info("获取用户信息");
    return restTemplate.getForObject("http://Server-Provider/user/{id}", User.class, id);
}

3. @CacheRemove Eliminación de caché. Debemos borrar la caché correspondiente a tiempo, de lo contrario causará inconsistencia entre los datos almacenados en caché y los datos reales.

@CacheRemove(commandKey = "getUserById")
@HystrixCommand
public void updateUser(@CacheKey("id") User user) {
    
    
    this.restTemplate.put("http://Server-Provider/user", user);
}

El atributo commandKey de @CacheRemove es consistente con el definido en getUser.

HystrixCollapser solicitar fusión

La fusión de solicitudes consiste en fusionar varias solicitudes únicas en una sola solicitud para llamar al proveedor de servicios, lo que reduce la carga del proveedor de servicios, una solución para una alta concurrencia. poco utilizado. Si desea verlo, haga clic en Spring Cloud Hystrix Service Fault Tolerance

Atributos de Hystrix

Método de configuración :

execution.isolation.strategy: Este atributo se utiliza para establecer la estrategia de aislamiento de ejecución, tiene las siguientes dos opciones, el valor predeterminado: THREAD

  1. THREAD: Una estrategia de aislamiento a través de grupos de subprocesos. Se ejecuta en un subproceso separado y su límite de simultaneidad está limitado por el número de subprocesos en el grupo de subprocesos.
  2. SEMAPHORE: Una estrategia de aislamiento mediante semáforos. Se ejecuta en el hilo de llamada y su límite de concurrencia está limitado por el recuento de semáforos.

1. Configuración global: application.properties

hystrix.command.default.execution.isolation.strategy = "THREAD"

2. Ejemplo de configuración: application.properties

hystrix.command.{HystrixCommandKey}.execution.isolation.strategy = "THREAD"

HystrixCommandKey es el valor commandKey de @HystrixCommand

3. Configuración de la instancia: @HystrixProperty

    @HystrixCommand(fallbackMethod = "getUserDefault", 
            commandProperties = {
    
    @HystrixProperty(name = "execution.isolation.strategy", value"THREAD")})
    public User getUser(Long id) {
    
    
        log.info("获取用户信息");
        return restTemplate.getForObject("http://Server-Provider/user/{id}", User.class, id);
    }

Lista de atributos

ejecución ejecución configuración

execution.isolation.strategy: Este atributo se utiliza para establecer la estrategia de aislamiento de ejecución, tiene las siguientes dos opciones. Valor predeterminado: THREAD

  1. THREAD: Una estrategia de aislamiento a través de grupos de subprocesos. Se ejecuta en un subproceso separado y su límite de simultaneidad está limitado por el número de subprocesos en el grupo de subprocesos.
  2. SEMAPHORE: Una estrategia de aislamiento mediante semáforos. Se ejecuta en el hilo de llamada y su límite de concurrencia está limitado por el recuento de semáforos.

execution.isolation.thread.timeoutinMilliseconds: esta propiedad se utiliza para configurar el período de tiempo de espera de la ejecución de HystrixCommand, en milisegundos. Cuando el tiempo de ejecución de HystrixCommand excede el valor de configuración, Hystrix marcará el comando de ejecución como TIMEOUT e ingresará a la lógica de procesamiento de degradación del servicio. Valor predeterminado: 1000 milisegundos

execution.timeout.enabled: esta propiedad se utiliza para configurar la ejecución de HystrixCommand si se habilita el período de tiempo de espera. El valor predeterminado es verdadero; si se establece en falso, la configuración de la propiedad execution.isolation.thread.timeoutinMilliseconds ya no funcionará.

coreSize: este parámetro se utiliza para establecer el número de subprocesos centrales en el grupo de subprocesos de comando. Este valor es la ejecución máxima simultánea de comandos. Predeterminado: 10

execution.isolation.semaphore.maxConcurrentRequests: Cuando la estrategia de aislamiento HystrixCommand usa un semáforo, esta propiedad se usa para configurar el tamaño del semáforo (el número de solicitudes concurrentes). Cuando el número máximo de solicitudes simultáneas alcanza el valor establecido, las solicitudes posteriores serán rechazadas. Predeterminado: 10

fallback.enabled: este atributo se utiliza para establecer si la política de degradación del servicio está habilitada. Si se establece en falso, cuando la solicitud falla o se rechaza, no se llamará al servicio degradado. Predeterminado: verdadero

Configuración del fusible del disyuntor

CircuitBreaker.enabled: este atributo se usa para determinar si se debe usar un interruptor automático para rastrear sus indicadores de salud y la solicitud del interruptor automático cuando falla el comando de solicitud de servicio. Predeterminado: verdadero

circuitBreaker.requestVolumeThreshold: esta propiedad se utiliza para establecer el número mínimo de solicitudes de fusibles de interruptores automáticos en la ventana de tiempo continuo. Por ejemplo, cuando el valor predeterminado es 20, si solo se reciben 19 solicitudes dentro de la ventana de tiempo continuo (10 segundos por defecto), incluso si las 19 solicitudes fallan, el disyuntor no se abrirá. Predeterminado: 20

circuitBreaker.errorThresholdPercentage: esta propiedad se utiliza para establecer la condición de porcentaje de error para abrir el interruptor automático. Por ejemplo, cuando el valor predeterminado es 5000, significa que en la ventana de tiempo continuo, si el número de solicitudes excede el valor de circuitBreaker.requestVolumeThreshold, si el porcentaje del número de solicitudes de error excede 50, el disyuntor se establece en el estado "abierto". De lo contrario, se establece en el estado "desactivado". Predeterminado: 50

circuitBreaker.sleepWindowinMilliseconds: esta propiedad se utiliza para establecer la ventana de tiempo de reposo después de que se abre el disyuntor. Una vez finalizada la ventana de tiempo de reposo, el disyuntor se establecerá en el estado "medio abierto" y se intentará el comando de solicitud de fusión. Si aún falla, el disyuntor seguirá estando en la posición "abierto". estado, y si tiene éxito, se establecerá en el estado "cerrado". Predeterminado: 5000

circuitBreaker.forceOpen: si esta propiedad se establece en true, el interruptor automático se verá obligado a entrar en el estado "abierto" y rechazará todas las solicitudes. Este atributo tiene prioridad sobre el atributo circuitBreaker.forceClosed.

CircuitBreaker.forceClosed: si esta propiedad se establece en true, el interruptor automático se verá obligado a entrar en el estado "cerrado" y recibirá todas las solicitudes. Si la propiedad circuitBreaker.forceOpen es verdadera, esta propiedad no tendrá efecto. Predeterminado: falso

requestContext

requestCache.enabled: esta propiedad se usa para configurar si se habilita el almacenamiento en caché de solicitudes.

Para conocer otros atributos, consulte Tolerancia a fallas del servicio Spring Cloud Hystrix

Principio de Hystrix

Flujo de procesamiento de Hystrix

Inserte la descripción de la imagen aquí

Aislamiento de recursos

El aislamiento de recursos se refiere principalmente al aislamiento de subprocesos. Hystrix proporciona dos métodos de aislamiento de subprocesos: grupo de subprocesos y semáforo.

Grupo de subprocesos de aislamiento de subprocesos

Hystrix usa el modo de comando para desacoplar el objeto que envía la solicitud y el objeto que ejecuta la solicitud, y encapsula diferentes tipos de solicitudes comerciales en las solicitudes de comando correspondientes.

Por ejemplo, pedir servicio de consulta de producto, consulta de solicitud de producto -> comando de producto; servicio de producto consulta de inventario, consulta de solicitud de inventario -> comando de inventario. Y configure un grupo de subprocesos para cada tipo de comando. Cuando se crea el comando por primera vez, se crea un grupo de subprocesos de acuerdo con la configuración y se coloca en ConcurrentHashMap, como Commodity Command:

final static ConcurrentHashMap<String, HystrixThreadPool> threadPools = new ConcurrentHashMap<String, HystrixThreadPool>();
...
if (!threadPools.containsKey(key)) {
    
    
    threadPools.put(key, new HystrixThreadPoolDefault(threadPoolKey, propertiesBuilder));
}

Cuando se crea el comando para solicitudes de consulta de productos posteriores, el grupo de subprocesos creado se reutilizará.
Inserte la descripción de la imagen aquí
Aislamiento de hilo-semáforo

Configure el semáforo para limitar el número de llamadas simultáneas a cualquier dependencia dada.

Cuando se usa el grupo de subprocesos, el subproceso que envía la solicitud y el subproceso que ejecuta el servicio dependiente no son el mismo. Cuando se usa el semáforo, el subproceso que envía la solicitud y el subproceso que ejecuta el servicio dependiente son los mismos, y ambos son el hilo que inicia la solicitud.
Inserte la descripción de la imagen aquí
Resumen de aislamiento de subprocesos

Cambio de hilo Soporte asincrónico Tiempo de espera de soporte Fusible de soporte Limitante Gastos generales
señal No No No
Grupo de hilos

En circunstancias normales, la sobrecarga introducida por el grupo de subprocesos es lo suficientemente pequeña como para que no haya un impacto significativo en el costo o el rendimiento. Pero para algunos servicios con una latencia de acceso muy baja, como depender solo de la memoria caché, la sobrecarga introducida por el grupo de subprocesos es más obvia. En este momento, la tecnología de aislamiento del grupo de subprocesos no es adecuada. Debemos considerar un método más ligero , como señales Aislamiento de volumen.

Tanto el grupo de subprocesos como el semáforo admiten la interrupción del circuito y la limitación de corriente. En comparación con los grupos de subprocesos, los semáforos no requieren cambio de subproceso, evitando así una sobrecarga innecesaria. Pero el semáforo no admite asíncrono, ni admite timeout, lo que significa que cuando el servicio solicitado no está disponible, el semáforo controlará la solicitud que exceda el límite para regresar de inmediato, pero el hilo que ya sostiene el semáforo solo puede esperar para la respuesta del servicio o desde el tiempo de espera Retorno, es decir, puede ocurrir una larga espera. En el modo de grupo de subprocesos, cuando el servicio que no responde excede el tiempo especificado, Hystrix notificará al subproceso para que finalice inmediatamente y regrese respondiendo a la interrupción.

Flujo de trabajo de fusible

El proceso detallado del fusible es el siguiente:

El primer paso es llamar a allowRequest () para determinar si se permite enviar la solicitud al grupo de subprocesos.

  1. Si el fusible se abre a la fuerza, circuitBreaker.forceOpen es verdadero y no se permite la liberación, y regresa.
  2. Si el fusible se cierra a la fuerza, circuitBreaker.forceClosed es verdadero, lo que permite la liberación. Además, no es necesario prestar atención al estado real del fusible, lo que significa que el fusible seguirá manteniendo las estadísticas y el estado del interruptor, pero no tendrá efecto.

El segundo paso es llamar a isOpen () para determinar si el interruptor del fusible está abierto. Si el interruptor del fusible está abierto, vaya al tercer paso, de lo contrario continúe;

  1. Si el número total de solicitudes en un ciclo es menor que el valor de circuitBreaker.requestVolumeThreshold, la solicitud puede pasar; de lo contrario, continúa;
  2. Si la tasa de error en un período es menor que el valor de circuitBreaker.errorThresholdPercentage, se permite que la solicitud pase. De lo contrario, abra el interruptor de fusibles y entre en el tercer paso.

El tercer paso es llamar a allowSingleTest () para determinar si se permite pasar una sola solicitud y verificar si se restablece el servicio dependiente.

  1. Si se abre el fusible y el tiempo transcurrido desde que se abre el fusible o el tiempo de la última solicitud de prueba libera el valor de circuitBreaker.sleepWindowInMilliseconds, el fusible entra en el estado semiabierto, lo que permite que se libere una solicitud de prueba; de lo contrario, no está permitido liberar.

Supongo que te gusta

Origin blog.csdn.net/fangye1/article/details/111614511
Recomendado
Clasificación