10 imágenes le muestran qué es la limitación de corriente, el disyuntor, la degradación del servicio

En un sistema distribuido, si un nodo de servicio falla o la red es anormal, puede causar que la persona que llama se bloquee y espere Si el tiempo de espera se establece en mucho tiempo, es probable que se agoten los recursos de la persona que llama. Esto, a su vez, provocó que el sistema ascendente de la persona que llama se quedara sin recursos, lo que finalmente provocó una avalancha del sistema.

Como se muestra abajo:

Si el servicio D falla y no puede responder, el servicio B solo puede bloquear y esperar cuando llama a D. Si el servicio B llama al servicio D y establece el tiempo de espera en 10 segundos y la tasa de solicitud es de 100 solicitudes por segundo, entonces se bloquearán 1000 subprocesos de solicitud esperando dentro de 10 segundos. El agotamiento de recursos no ha podido proporcionar servicios externos. Esto, a su vez, afectó a los servicios del sistema de entrada A, lo que eventualmente provocó el colapso total del sistema.

Mejorar la tolerancia general a fallos del sistema es un medio eficaz para evitar avalanchas en el sistema.

En el artículo "Microservicios: una definición de este nuevo término arquitectónico" [1] de Martin Fowler y James Lewis, se proponen 9 características de los microservicios, una de las cuales es el diseño tolerante a fallas.

Para evitar que el sistema sufra avalanchas, debe tener un diseño tolerante a fallas. En el caso de un flujo de tráfico repentino, la práctica general es usar interruptores de circuito y medidas de degradación del servicio para las funciones comerciales no centrales para proteger los servicios normales de las funciones comerciales centrales, mientras que para los servicios de funciones centrales, se requieren medidas de limitación de flujo.

Hoy, hablemos sobre la limitación de corriente, el disyuntor y la degradación del servicio en la tolerancia a fallas del sistema.

1 límite de corriente

Cuando la capacidad de procesamiento del sistema no puede hacer frente al flujo repentino de solicitudes externas, para evitar que el sistema se bloquee, se deben tomar medidas para limitar el flujo.

1.1 Indicadores de limitación de corriente

1.1.1 TPS

El rendimiento del sistema es un indicador clave para medir el rendimiento del sistema, y ​​lo más razonable es limitar la corriente de acuerdo con la cantidad de transacciones completadas.

Sin embargo, a efectos prácticos, no es realista limitar el flujo según la transacción. Completar una transacción en un sistema distribuido requiere la cooperación de múltiples sistemas. Por ejemplo, al comprar en un sistema de comercio electrónico, necesitamos varios servicios, como el pedido, el inventario, la cuenta y el pago para completar. Algunos servicios deben devolverse de forma asincrónica, por lo que puede llevar mucho tiempo completar una transacción. Si la corriente está limitada según TPS, la granularidad de tiempo puede ser muy grande y es difícil evaluar con precisión el rendimiento de respuesta del sistema.

1.1.2 HPS

El número de solicitudes por segundo se refiere al número de solicitudes que el servidor recibe de los clientes por segundo.

Si una solicitud completa una transacción, entonces TPS y HPS son equivalentes. Sin embargo, en un escenario distribuido, es posible que se requieran múltiples solicitudes para completar una transacción, por lo que los indicadores TPS y HPS no se pueden tratar por igual.

1.1.3 QPS

El número de solicitudes de consulta del cliente a las que el servidor puede responder por segundo.

Si solo hay un servidor en segundo plano, HPS y QPS son equivalentes. Sin embargo, en un escenario distribuido, cada solicitud requiere que varios servidores cooperen para completar la respuesta.

Los métodos de limitación de corriente convencionales actuales utilizan principalmente HPS como indicador de limitación de corriente.

1.2 Método de limitación de corriente

1.2.1 Contador de flujo

Este es el método más simple y directo, como limitar el número de solicitudes por segundo a 100 y rechazar más de 100 solicitudes.

Pero hay 2 problemas obvios con este método:

  • La unidad de tiempo (como 1s) es difícil de controlar, como se muestra en la siguiente figura: En esta imagen, el HPS no excede 100 desde el tiempo de abajo, pero HPS excede 100 desde arriba.
  • Hay un período de tiempo en el que el tráfico excede, y no es necesariamente necesario limitar la corriente.Como se muestra en la figura a continuación, el límite de HPS del sistema es 50. Aunque el tráfico excede los primeros 3 s, si se establece el tiempo de espera a 5s, no se requiere el límite actual.

1.2.2 Ventana de tiempo deslizante

El algoritmo de ventana de tiempo deslizante es un algoritmo limitador de corriente popular.La idea principal es considerar el tiempo como una ventana que avanza, como se muestra en la siguiente figura:

Al principio, consideramos t1~t5 como una ventana de tiempo, cada ventana es de 1 s. Si nuestro objetivo de límite actual es de 50 solicitudes por segundo, la suma de solicitudes en la ventana t1~t5 no puede exceder las 250.

Esta ventana se desliza y la ventana del segundo siguiente se convierte en t2 ~ t6. En este momento, las estadísticas del segmento de tiempo t1 se descartan y se agregan al segmento de tiempo t6 para las estadísticas. El número de solicitudes durante este período tampoco puede exceder las 250.

La ventaja de la ventana de tiempo deslizante es resolver los defectos del algoritmo del contador de tráfico, pero también hay 2 problemas:

  • Si el tráfico excede, se debe descartar o degradar la lógica
  • El control de flujo no es lo suficientemente preciso para limitar el flujo concentrado en un corto período de tiempo, ni puede cortar picos y llenar valles

1.2.3 Algoritmo de cubeta con fugas

La idea del algoritmo del balde con fugas es la siguiente:

Antes de que la solicitud del cliente se envíe al servidor, el depósito con fugas se utiliza para almacenarlo en caché. El depósito con fugas puede ser una cola con una longitud fija, y las solicitudes en la cola se envían uniformemente al servidor.

Si la tasa de solicitud del cliente es demasiado rápida y la cola del depósito con fugas está llena, se rechazará o se ejecutará la lógica de procesamiento de degradación. De esta forma, el servidor no se verá afectado por el tráfico de ráfagas.

La ventaja del algoritmo de cubeta con fugas es que es fácil de implementar y las colas de mensajes se pueden usar para reducir los picos y llenar los valles.

Pero también hay 3 cuestiones a considerar:

  • Si el tamaño del depósito con fugas es demasiado grande, puede generar una mayor presión de procesamiento en el servidor; si es demasiado pequeño, se puede descartar una gran cantidad de solicitudes.
  • La tasa de envío de solicitudes del depósito con fugas al servidor.
  • El uso del método de solicitud de caché hará que el tiempo de respuesta de la solicitud sea más largo.

Los dos valores de tamaño de depósito con fugas y tasa de envío se seleccionarán de acuerdo con los resultados de la prueba en la etapa inicial del proyecto. Sin embargo, con la mejora de la arquitectura y el escalado del clúster, estos dos valores también cambiar en consecuencia.

1.2.4 Algoritmo de depósito de fichas

El algoritmo del cubo de fichas es como un paciente que va a un hospital a ver a un médico. Antes de buscar un médico, primero debe registrarse, y la cantidad de números que el hospital emite todos los días es limitada. Si se agota el número del día, se liberará otro lote al día siguiente.

La idea básica del algoritmo es ejecutar periódicamente el siguiente proceso:

Cuando el cliente envía una solicitud, primero debe obtener el token del depósito de tokens. Si se obtiene, puede enviar la solicitud al servidor. Si no se puede obtener el token, solo se puede rechazar o la lógica del servicio Se puede utilizar la degradación. Como se muestra abajo:

El algoritmo del cubo de fichas resuelve el problema del algoritmo del cubo con fugas, y la implementación no es complicada, y se puede realizar utilizando el semáforo. Es más utilizado en escenarios de limitación de corriente reales. Por ejemplo, la guayaba de Google implementa la limitación de corriente del algoritmo token bucket. Si está interesado, puede estudiarlo.

1.2.5 Limitación de corriente distribuida

Si en el escenario del sistema distribuido, ¿siguen siendo aplicables los cuatro algoritmos de limitación de corriente presentados anteriormente?

Tomando el algoritmo del balde de fichas como ejemplo, si un cliente realiza un pedido en el sistema de comercio electrónico, como se muestra a continuación:

Si guardamos el cubo de fichas en un lugar separado (como redis) para todo el sistema distribuido, el cliente está llamando al servicio compuesto y el servicio compuesto llama a los servicios de pedidos, inventario y cuenta para interactuar con el cubo de fichas, y el Número de interacciones Incrementado significativamente.

Una mejora es que el cliente primero obtiene cuatro tokens antes de llamar al servicio compuesto, resta un token cuando llama al servicio compuesto y pasa tres tokens al servicio compuesto, y consume un token a su vez cuando el servicio compuesto llama a los siguientes tres servicios.

1.2.6 limitación de corriente hystrix

hystrix puede usar semáforos y grupos de subprocesos para limitar la corriente.

1.2.6.1 Límite de corriente del semáforo

hystrix puede usar semáforos para limitar la corriente, como agregar las siguientes anotaciones al método de prestación de servicios. De esta forma, solo 20 hilos concurrentes pueden acceder a este método, y el exceso se transferirá al método degradado errMethod.

@HystrixCommand(
 commandProperties= {
   @HystrixProperty(name="execution.isolation.strategy", value="SEMAPHORE"),
   @HystrixProperty(name="execution.isolation.semaphore.maxConcurrentRequests", value="20")
 },
 fallbackMethod = "errMethod"
)

1.2.6.2 Límite de corriente del conjunto de subprocesos

hystrix también puede usar el grupo de subprocesos para limitar la corriente, agregue las siguientes anotaciones al método de prestación de servicios, cuando la cantidad de subprocesos

@HystrixCommand(
    commandProperties = {
            @HystrixProperty(name = "execution.isolation.strategy", value = "THREAD")
    },
    threadPoolKey = "createOrderThreadPool",
    threadPoolProperties = {
            @HystrixProperty(name = "coreSize", value = "20"),
   @HystrixProperty(name = "maxQueueSize", value = "100"),
            @HystrixProperty(name = "maximumSize", value = "30"),
            @HystrixProperty(name = "queueSizeRejectionThreshold", value = "120")
    },
    fallbackMethod = "errMethod"
)

Tenga en cuenta aquí: en el grupo de subprocesos de Java, si la cantidad de subprocesos supera el coreSize, la solicitud para crear un subproceso ingresará primero en la cola. Si la cola está llena, continuará creando subprocesos hasta que la cantidad de subprocesos alcance el maximumSize y, a continuación, siga la política de rechazo. Sin embargo, hay un parámetro más queueSizeRejectionThreshold en el conjunto de subprocesos configurado por hystrix.Si queueSizeRejectionThreshold < maxQueueSize, el número de colas alcanza queueSizeRejectionThreshold y se seguirá la estrategia de rechazo, por lo que el tamaño máximo no es válido. Si queueSizeRejectionThreshold > maxQueueSize, cuando el número de colas alcanza maxQueueSize, el tamaño máximo es válido y el sistema continuará creando subprocesos hasta que el número alcance el tamaño máximo. Pozo de ajuste de grupo de hilos Hytrix [2]

2 soplado

Creo que todo el mundo está familiarizado con los interruptores automáticos, es equivalente a un interruptor, que puede evitar el paso del tráfico cuando está encendido. Por ejemplo, un fusible, cuando la corriente es demasiado grande, se quemará, evitando así daños a los componentes.

Fusible de servicio significa que la persona que llama accede al servicio a través del disyuntor como un proxy. El disyuntor observará continuamente el estado de éxito y falla devuelto por el servicio. Cuando la falla supera el umbral establecido, el disyuntor se abrirá y el solicitud no puede realmente acceder al servicio. .

Para una mejor comprensión, he dibujado el siguiente diagrama de tiempo:

2.1 Estado del interruptor automático

Un interruptor automático tiene 3 estados:

  • CERRADO: Estado por defecto. El disyuntor observa que el porcentaje de solicitudes fallidas no alcanza el umbral, y el disyuntor considera que el servicio de proxy está en buenas condiciones.
  • ABIERTO: El disyuntor observa que la proporción de solicitudes fallidas ha alcanzado el umbral. El disyuntor considera que el servicio proxy es defectuoso y enciende el interruptor. La solicitud ya no llega al servicio proxy, pero falla rápidamente.
  • MEDIO ABIERTO: Después de abrir el disyuntor, para restaurar automáticamente el acceso al servicio proxy, cambiará al estado medio abierto e intentará solicitar el servicio proxy para ver si el servicio se ha recuperado. Si tiene éxito, pasará al estado CERRADO, de lo contrario, pasará al estado ABIERTO.

El diagrama de transición de estado del interruptor automático es el siguiente:

2.2 Cuestiones a tener en cuenta

Hay algunas cosas a tener en cuenta al usar interruptores automáticos:

  • Para diferentes excepciones, defina una lógica de procesamiento posterior al fusible diferente.
  • Establezca la duración de la fusión y cambie a MEDIO ABIERTO para volver a intentarlo después de esta duración.
  • Registre registros de fallas de solicitudes para monitoreo.
  • Para el reintento activo, por ejemplo, para el fusible causado por el tiempo de espera de la conexión, puede usar subprocesos asíncronos para realizar la detección de red, como telenet, y cambiar a MEDIO ABIERTO para volver a intentar cuando detecta que la red está desbloqueada.
  • Interfaz de compensación, el disyuntor puede proporcionar una interfaz de compensación para que el personal de operación y mantenimiento cierre manualmente.
  • Al volver a intentarlo, puede usar la solicitud fallida anterior para volver a intentarlo, pero debe prestar atención a si la empresa lo permite.

2.3 Escenarios de uso

  • Hacer que el cliente falle rápidamente cuando el servicio falla o se actualiza
  • La lógica de manejo de fallas es fácil de definir
  • La respuesta tarda mucho tiempo y el tiempo de espera de lectura establecido por el cliente será relativamente largo, lo que evitará que los recursos de conexión y subproceso se liberen debido a una gran cantidad de solicitudes de reintento por parte del cliente.

3 Rebaja de servicio

Hablé sobre la limitación y fusión de corriente, en contraste, la degradación del servicio se considera desde la perspectiva del sistema en general.

Una vez que el servicio se agota, generalmente se permite que la solicitud pase por el método de procesamiento preconfigurado, que es una lógica de degradación.

La degradación del servicio consiste en degradar los servicios no esenciales y no críticos.

3.1 Escenarios de uso

  • El servicio maneja las excepciones y envía la información de la excepción directamente al cliente, sin ninguna otra lógica.
  • El servicio maneja las excepciones, almacena en caché la solicitud, devuelve un estado intermedio al cliente y luego vuelve a intentar la solicitud almacenada en caché.
  • Cuando el sistema de monitoreo detecta un aumento repentino en el tráfico, para evitar que las funciones comerciales no centrales consuman recursos del sistema, estas funciones no centrales se desactivan.
  • La presión de solicitud de la base de datos es alta, puede considerar devolver los datos en el caché
  • Para operaciones de escritura que consumen mucho tiempo, se puede cambiar a escritura asíncrona
  • Cierre temporalmente las tareas por lotes en ejecución para ahorrar recursos del sistema

3.2 Rebajar usando hystrix

3.2.1 Rebaja anormal

Cuando se degrada hystrix, puede ignorar una excepción y agregar la anotación @HystrixCommand al método:

El código siguiente define el método de degradación como errMethod y no degrada las excepciones ParamErrorException y BusinessTypeException.

@HystrixCommand(
 fallbackMethod = "errMethod",
 ignoreExceptions = {ParamErrorException.class, BusinessTypeException.class}
)

3.2.2 Degradación del tiempo de espera de la llamada

Específicamente para llamar a la degradación del tiempo de espera de la interfaz de terceros.

El siguiente método consiste en llamar a la interfaz de terceros y cambiar al método errMethod sin recibir una respuesta durante 3 segundos.

@HystrixCommand(
    commandProperties = {
            @HystrixProperty(name="execution.timeout.enabled", value="true"),
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="3000"),
    },
    fallbackMethod = "errMethod"
)

Resumir

La limitación de corriente, la fusión y la degradación del servicio son patrones de diseño importantes para la tolerancia a fallas del sistema.En cierto sentido, la limitación de corriente y la degradación del servicio también son medios de degradación del servicio.

Los interruptores automáticos y la degradación del servicio están dirigidos principalmente a funciones comerciales no centrales, y si el proceso comercial principal excede el valor máximo estimado, se debe realizar una limitación de corriente.

Para la limitación de corriente, es muy importante elegir un algoritmo de limitación de corriente razonable. El algoritmo de cubo de fichas tiene ventajas obvias y también es el algoritmo de limitación de corriente más utilizado.

Durante el diseño del sistema, estos modos deben configurarse con los umbrales correspondientes junto con la estimación del volumen comercial y los datos de prueba de rendimiento, y estos umbrales se almacenan mejor en el centro de configuración para facilitar la modificación en tiempo real.

Supongo que te gusta

Origin blog.csdn.net/m0_63437643/article/details/123733529
Recomendado
Clasificación