En el desarrollo de software, es común que las aplicaciones se comuniquen con servicios o recursos externos, como bases de datos, APIs o microservicios. Sin embargo, estos servicios o recursos pueden fallar o estar temporalmente indisponibles por diversas razones, lo que puede afectar el rendimiento y la disponibilidad de la aplicación.
Para manejar estos escenarios de falla, se puede utilizar el patrón Circuit
Breaker, que consiste en detectar y prevenir que una operación que tiene alta
probabilidad de fallar se ejecute repetidamente, causando más problemas o
consumiendo recursos innecesarios.
El patrón Circuit Breaker tiene tres estados posibles: cerrado, abierto y medio abierto.
- Cerrado: En este estado, el
circuito está funcionando normalmente y la operación se ejecuta sin problemas.
Si se detecta una falla, se incrementa un contador de fallas y se calcula un
umbral de fallas, que puede ser un número o un porcentaje de fallas permitidas.
Si el contador de fallas supera el umbral, el circuito pasa al estado abierto.
- Abierto: En este estado, el circuito está roto y la operación no se ejecuta, sino que se devuelve un error inmediatamente. Esto evita que la aplicación siga intentando una operación que seguramente va a fallar. Además, se establece un tiempo de espera para que el circuito se recupere. Después de transcurrido el tiempo de espera, el circuito pasa al estado medio abierto.
- Medio abierto: En este estado, el circuito está en proceso de recuperación y se prueba si la falla se ha resuelto. Para ello, se permite que una operación se ejecute y se evalúa el resultado. Si la operación tiene éxito, el circuito pasa al estado cerrado y se reinicia el contador de fallas. Si la operación falla, el circuito vuelve al estado abierto y se espera otro tiempo de espera.
El patrón Circuit Breaker tiene
varios beneficios, como:
- Mejorar la estabilidad y la
resiliencia de la aplicación, al evitar que se propague el efecto de una falla
a otras partes del sistema.
- Reducir el tiempo de respuesta de
la aplicación, al evitar esperar por operaciones que van a fallar o que tienen
un tiempo de espera muy largo.
- Proporcionar una
retroalimentación rápida al usuario o al sistema, al devolver un error o una
respuesta alternativa en lugar de bloquear la ejecución.
- Facilitar la recuperación de la aplicación, al permitir que se reanude la operación cuando el servicio o recurso externo esté disponible nuevamente.
Ejemplo:
Una aplicación se conecta a una base de datos 100
veces por segundo y la base de datos falla. El arquitecto no
quiere que el mismo error se repita constantemente. También quiere manejar el
error de forma rápida y elegante sin esperar por el tiempo de espera de la
conexión TCP. En este caso, se puede usar un circuito que se abra cuando se
detecte una falla en la base de datos y se cierre cuando se restablezca la
conexión.
¿Cómo se puede implementar el patrón Circuit Breaker con AWS Step Functions?
AWS Step Functions es un servicio de orquestación que permite
integrar diversos servicios de AWS para construir
aplicaciones. Cada paso de un flujo de trabajo se llama estado. Un estado puede representar
una unidad de trabajo que realiza otro servicio de AWS, como AWS Lambda, o una
decisión lógica, como un bifurcación o una unión.
Uno de los componentes del Step Functions es el MapState, el cuál permite ejecutar una tarea en paralelo para
cada elemento de un array de entrada. Por ejemplo, se puede usar un MapState
para procesar una colección de imágenes.
MapState
Un MapState recibe como entrada un array de objetos que contienen las referencias a las imágenes y devuelve como salida un array de objetos que contienen las referencias a las imágenes procesadas.
Al ejecutar tareas en paralelo, se puede encontrar el problema de que algunas de ellas fallen (problemas de saturación), lo que puede generar un uso innecesario de un servicio indispuesto. Para manejar este problema, se puede usar el patrón Circuit Breaker en el MapState, definiendo un umbral de fallos. Este valor permite especificar el número/porcentaje de elementos que pueden fallar, si este umbral tal es superado, el circuito se abre y la ejecución de las tareas en paralelo se detienen.
Ejemplo:
Se
tiene un flujo de trabajo que procesa una gran cantidad de datos con un
servicio de AWS, como AWS Glue, y se quiere evitar que el flujo de trabajo
falle por completo si algunos de los datos son inválidos o causan un error. En
este caso, se puede usar un estado Map para ejecutar una tarea de AWS Glue para
cada elemento de un array de datos y definir un umbral de fallas tolerado que
permita que el flujo de trabajo continúe si solo falla un pequeño porcentaje de
los datos.
Conclusión
-
El patrón Circuit Breaker es una forma de mejorar la robustez y la eficiencia
de las aplicaciones que se comunican con servicios o recursos externos, al
evitar que se ejecuten operaciones que tienen alta probabilidad de fallar y al
permitir que se recuperen cuando sea posible.
- Con el estado Map de Step Functions, se puede ejecutar una tarea en paralelo para cada elemento de una matriz de entrada y definir un umbral de fallas tolerado que implemente el patrón Circuit Breaker. Esto permite que el flujo de trabajo se adapte a las fallas o demoras de las tareas en paralelo y que se complete con éxito.