REL 5: ¿Cómo diseña interacciones en un sistema distribuido para mitigar o tolerar errores?
Los sistemas distribuidos dependen de las redes de comunicación para interconectar los componentes (como servidores o servicios). A pesar de la pérdida de datos o la latencia sobre estas redes, su carga de trabajo debe funcionar de manera confiable. Los componentes del sistema distribuido deben funcionar de manera que no afecten negativamente a otros componentes o a la carga de trabajo. Las prácticas recomendadas permiten que las cargas de trabajo toleren errores o presiones, se recuperen más rápido de estos y mitiguen el impacto de dichas dificultades. El resultado es un mejor tiempo promedio de recuperación (MTTR).
Recursos
Retry, backoff, and jitter: AWS re:Invent 2019: Introducing The Amazon Builders’ Library
(DOP328)
Error Retries and Exponential Backoff in AWS
Amazon API Gateway: Throttle API Requests for Better Throughput
The Amazon Builders' Library: Timeouts, retries, and backoff with jitter
The Amazon Builders' Library: Avoiding fallback in distributed systems
The Amazon Builders' Library: Avoiding insurmountable queue backlogs
The Amazon Builders' Library: Caching challenges and strategies
Well-Architected lab: Level 300: Implementing Health Checks and Managing Dependencies
to Improve Reliability
CircuitBreaker (summarizes Circuit Breaker from “Release It!” book)
Michael Nygard “Release It! Design and Deploy Production-Ready Software”
Prácticas recomendadas:
-
Implemente una degradación ordenada para transformar las dependencias estrictas aplicables en dependencias flexibles: Cuando las dependencias de un componente no están en buen estado, el componente en sí puede funcionar, aunque de manera degradada. Por ejemplo, cuando una llamada de dependencia falla, se conmuta por error a una respuesta estática predeterminada.
-
Limite las solicitudes: Se trata de un patrón de mitigación para responder a un aumento inesperado en la demanda. Algunas solicitudes se cumplen, pero aquellas solicitudes que superan un límite definido son rechazadas y devuelven un mensaje que indica que fueron limitadas. Se espera que los clientes se retiren y abandonen la solicitud o lo intenten nuevamente a una velocidad mucho menor.
-
Controle y limite las llamadas de reintento: Utilice un retardo exponencial para volver a intentar después de intervalos progresivamente más largos. Introduzca la fluctuación para aleatorizar esos intervalos de reintentos y limite la cantidad máxima de reintentos.
-
Implemente las notificaciones rápidas de errores y limite las colas: Si la carga de trabajo no puede responder de forma correcta a una solicitud, muestre una notificación rápida de error. Esto permite la liberación de recursos asociados con una solicitud. Además, si se están agotando los recursos, permite al servicio recuperarse. Si la carga de trabajo puede responder correctamente, pero la tasa de solicitudes es demasiado alta, en su lugar, utilice una cola para almacenar en búfer las solicitudes. Sin embargo, no permita que se formen colas largas que lo lleven a tratar solicitudes obsoletas que el cliente ya ha desestimado.
-
Establezca tiempos de espera para los clientes: Establezca tiempos de espera adecuadamente, verifíquelos de manera sistemática y no confíe en los valores predeterminados, ya que, por lo general, están establecidos demasiado altos
-
Cree servicios sin estado siempre que sea posible: Los servicios no deberían requerir un estado o deberían descargar el estado de manera tal que, entre las solicitudes de clientes diferentes, no haya dependencia en datos almacenados localmente en un disco o una memoria. Esto permite que los servidores se reemplacen voluntariamente sin afectar la disponibilidad. Amazon ElastiCache o Amazon DynamoDB son destinos adecuados para los estados descargados.
-
Implemente palancas de emergencia: Se trata de procesos rápidos que pueden mitigar el impacto en la disponibilidad de su carga de trabajo. Se pueden ejecutar en caso de ausencia de una causa raíz. La palanca de emergencia ideal reduce la carga cognitiva de los encargados de solucionar los problemas a cero a través de criterios totalmente deterministas de activación y desactivación. Algunos ejemplos de palancas incluyen bloquear todo el tráfico robotizado o brindar una respuesta estática. Por lo general, las palancas son manuales, pero también pueden ser automatizadas.
Plan de mejora
Implemente una degradación ordenada para transformar las dependencias estrictas aplicables
en dependencias flexibles
- Al devolver una respuesta estática, su carga de trabajo mitiga los errores que ocurren
en sus dependencias
Well-Architected lab: Level 300: Implementing Health Checks and Managing Dependencies to Improve Reliability - Detecte cuándo la operación de reintento puede producir un error y evite que su cliente
realice llamadas fallidas con el patrón del interruptor de circuitos
CircuitBreaker
Limite las solicitudes
- Use Amazon API Gateway
Throttle API Requests for Better Throughput
Controle y limite las llamadas de reintento
Error Retries and Exponential Backoff in AWS
- Los SDK de Amazon implementan esto de manera predeterminada. Implemente una lógica similar en su capa de dependencia cuando llame a sus propios servicios dependientes. Decida cuáles son los tiempos de espera y cuándo dejar de volver a intentar según su caso de uso.
Implemente las notificaciones rápidas de errores y limite las colas
- Implemente las notificaciones rápidas de errores cuando el servicio esté bajo presión
Fail Fast - Limite las colas: En un sistema basado en colas, cuando el procesamiento se detiene pero los mensajes
siguen llegando, la cola de mensajes puede acumularse en una lista grande, lo que
aumenta el tiempo de procesamiento. El trabajo se puede completar demasiado tarde
como para que los resultados sean útiles, lo que afecta la disponibilidad que la cola
debía proteger.
The Amazon Builders' Library: Avoiding insurmountable queue backlogs
Establezca tiempos de espera para los clientes
AWS SDK: Retries and Timeouts
Cree servicios sin estado siempre que sea posible
- Elimine el estado que realmente podría almacenarse en los parámetros de solicitud.
- Algunos datos (como cookies) se pueden pasar en encabezados o parámetros de consulta.
- Refactorice para eliminar el estado que puede pasarse rápidamente en las solicitudes.
- Después de examinar si el estado es necesario, mueva cualquier seguimiento de estado
a un almacén de datos o caché resistente de múltiples zonas como Amazon ElastiCache,
Amazon RDS, Amazon DynamoDB o una solución distribuida de datos de terceros: Almacene el estado que no pudo moverse a almacenes de datos resistentes.
- Algunos datos pueden no necesitarse por solicitud y pueden recuperarse según se los requiera.
- Elimine los datos que se pueden recuperar asincrónicamente.
- Decida sobre un almacén de datos que cumpla con los requisitos para el estado requerido.
- Considere crear una base de datos NoSQL para datos no relacionales.
Implemente palancas de emergencia
- Consejos para la implementación y el uso de palancas de emergencia
- Cuando se activen las palancas, haga MENOS, no más
- Manténgalo simple, evite el comportamiento bimodal
- Pruebe sus palancas de forma periódica
- Estos son ejemplos de acciones que NO constituyen palancas de emergencia
- Agregar capacidad
- Llamar a los propietarios de los servicios de los clientes que dependen de su servicio y solicitarles que disminuyan la cantidad de llamadas
- Efectuar un cambio en el código y lanzarlo