Circuit Breaker pattern

La llegada de nuevas arquitecturas como SOA o Microservicios han tra铆do grandes ventajas, pero con ello, han surgido nuevas problem谩ticas que pocas veces se sabe c贸mo resolver con precisi贸n, uno de estos casos, es identificar cuando un servicio ha dejado de funcionar para dejarle de enviar peticiones, pero por otro lado, identificar el fallo, reportarlo y hacer algo en consecuencia, por suerte, la patr贸n Circuit Breaker (Corto circuito) permite cerrar la comunicaci贸n con un determinado servicio cuando se ha detectado que est谩 fallado.

 

El patr贸n Circuit Breaker es muy parecido a un fusible, el cual se funde para evitar que una descarga el茅ctrica afecte al circuito, con la 煤nica diferencia de que el software, este fusible se puede restaurar cuando el problema all谩 pasado. Esto puede resultar un poco confuso, pero analicemos c贸mo funciona el patr贸n con el siguiente diagrama:

Circuit Breaker pattern diagrama de sequencia

 

Antes de explicar c贸mo funciona el diagrama, debemos de comprender que son y el rol que tiene cada uno de los componentes involucrados:

  • Client: representa al cliente que intenta consumir los servicios del Supplier, sin embargo, este lo hace por medio del Circuit Breaker.
  • Circuit Breaker: es el componente que se encarga de la comunicaci贸n con el Supplier, el cual, mantiene un registro del estado de salud del servicio que usar谩 para abrir el circuito cuando detecte que el Supplier est谩 fallando.
  • Supplier: representa el servicio de negocio remoto, el cual expone una serie de funcionalidad para ser consumida por el Client.

Una vez que entendemos esto, pasemos a explicar c贸mo funciona el patr贸n Circuit Breaker:

  1. El Client realiza una primera llamada al Supplier por medio del Circuit Breaker.
    1. El Circuit Breaker determina que el servicio est谩 operando correctamente el Supplier y redirecciona la petici贸n al Supplier.
    2. El Supplier responde correctamente y env铆a la respuesta al Circuit Breaker para que sea este quien finalmente reenv铆e la respuesta al Client.
  2. El Client env铆a nuevamente una petici贸n al Supplier por medio del Circuit Breaker
    1. El Circuit Breaker redirecciona la petici贸n al Supplier
    2. En esta ocasi贸n el Supplier responde con error o lanza un Timeout
    3. El Circuit Breaker recibe la respuesta de error y toma nota del error, el cual tiene un contado que determina cuantas veces ha fallado el Supplier de forma simult谩nea. En este caso, el contado de errores se establece en 1.
    4. El Circuit Breaker redirecciona el error al Client.
  3. Seguido de un tiempo, el Client env铆a nuevamente una petici贸n al Supplier por medio el Circuit Breaker.
    1. El Circuit Breaker redirecciona la petici贸n al Supplier
    2. El Supplier nuevamente responde con error o Timeout
    3. El Circuit Breaker recibe la respuesta de error e incrementa el contado de errores en 2.
      1. Dada una configuraci贸n, el Circuit Breaker puede determinar que 2 es el n煤mero m谩ximo de errores simult谩neos que puede tolerar antes de realiza el corto circuito y abre el circuito con el Supplier.
      2. Un paso opcional pero muy deseable es tener alg煤n componente de monitoreo que permite notificar a los administradores en tiempo real sobre los errores para poder tomar cartas en el asunto.
    4. El Circuit Breaker redirecciona el error al Client.
  4. El Client nuevamente env铆a una nueva petici贸n al Supplier por medio del Circuit Breaker.
    1. El Circuit Breaker determina el servicio no est谩 respondiendo debido a los dos errores anteriores, por lo que retorna un error al Client indic谩ndole que el Supplier est谩 fuera de servicio.

 

Como podemos observar en la explicaci贸n anterior, el Circuit Breaker puede determinar que un determinado servicio (Supplier) est谩 fuera de servicio al detectar que ha respondido con error de forma consecutiva un n煤mero determinado de veces.

 

NOTA: es com煤n confundirse con el termino abierto y cerrado, pues podemos pensar que el estado abierto es cuando el servicio est谩 disponible, sin embargo, como estamos utilizando la nomenclatura de los circuitos el茅ctricos, por lo que un circuito cerrado es cuando la electricidad flujo, por lo tanto, en este patr贸n, cerrado significa que existe comunicaci贸n con el Supplier.

 

 

Abriendo el circuito

En este punto te estar谩s preguntando, bien, ya he abierto el circuito, pero no me puedo quedar todo el tiempo as铆, necesito cerrarlo nuevamente una vez que el problema se ha resuelto. Pues bien, para eso, tenemos una funcionalidad adicional, en la cual configuramos cuanto tiempo debe esperar el Circuit Breaker antes de mandar una solicitud al Supplier. En este caso, por ejemplo, podr铆amos esperar una hora desde que se cerr贸 el circuito para enviar una nueva petici贸n, si esta petici贸n retorna exitosamente, el Circuit Breaker cerrar谩 nuevamente el circuito con el Supplier, pero, por el contrario, si este nuevamente retorna con error o Timeout, entonces el tiempo de espera se reiniciar谩 y esperar谩 otra hora antes de mandar una nueva petici贸n para comprobar su disponibilidad.

Circuit Breaker pattern Diagrama de secuencia abierto

 

Dicho lo anterior, veamos c贸mo quedar铆a el diagrama de secuencia para la reapertura del circuito:

  1. En la parte superior partimos del escenario donde hemos abierto el circuito, lo cual explicamos anteriormente, por lo que nos saltaremos esta explicaci贸n. Solo asumamos que, en este punto, el circuito se encuentra abierto.
  2. Una hora despu茅s de que el circuito se abri贸, el Circuit Breaker redirecciona la siguiente petici贸n al Supplier que estaba fallando para comprobar si ya se encuentra en funcionamiento.
    1. Tras redireccionar la petici贸n al Supplier, este falla nuevamente y redirecciona el error al Circuit Breaker.
    2. El Circuit Breaker al darse cuenta que sigue fallando, reinicia el contador para esperar otra hora antes de volver a intentar consumir los servicios del Supplier.
  3. Tras una hora desde el paso anterior, el Circuit Breaker redirecciona una nueva petici贸n al Supplier para comprobar si ya se encuentra en funcionamiento.
    1. En este caso, el Supplier ya se encuentra operando correctamente, por lo que recibe la petici贸n, la procesa y retornar exitosamente.
    2. El Circuit Breaker detecta la respuesta exitosa del Supplier y cierra nuevamente el circuito.

 

 

Circuit Breaker y los microservicios

En este punto ya hemos aprendido como es que el patr贸n Circuit Breaker abre el circuito ante una serie de errores consecutivos y como el circuito se cierra cuando el error es resuelto, pero hay algo de lo que no hemos hablado. 驴Te has preguntado que va a pasar con la aplicaci贸n si se abre el circuito? Es decir, una hora sin poder lanzar peticiones al Supplier podr铆a causar un caos en nuestra aplicaci贸n, pues no podremos hacer nada hasta que el circuito sea restaurado.

Pues bien, te tengo buenas noticias, este patr贸n no fue dise帽ado para aplicaciones Standalone, si no que fue dise帽ado para arquitecturas cloud, donde tenemos alta disponibilidad y escalamiento, lo que quiere decir que debemos de tener m煤ltiples instancias del Supplier, para asegurarnos de seguir operando ante la falla de una o m煤ltiples instancias del mismo Supplier:

Circuit Breaker pattern arquitectura

 

En la imagen anterior ya podemos observar c贸mo es que existe una serie de instancias de un mismo Supplier, por lo que en caso de que alguno falle, el Circuit Breaker deber谩 ser lo suficientemente inteligente para redireccionar la petici贸n a otro Supplier en caso de que el primero falle, de esta forma, no retornamos el error al cliente, si no que reintentamos la ejecuci贸n en el siguiente Supplier disponible.

 

 

Ciclo de vida del Circuit Breaker

El Circuit Breaker se puede implementar como m谩quina de estados, la cual puede pasar por 3 estados diferentes, y cada estado afectar谩 la forma en que funciona, los estados son:

  • Closed: Este estado indica que el servicio destino est谩 respondiendo correctamente. En caso de alcanzar un umbral de errores, pasar谩 al estado Open.
  • Open: Este estado indica que el servicio destino est谩 fallando, por lo que toda invocaci贸n regresara un error de inmediato. Tras un tiempo de espera, pasar谩 a estado Half-Open.
  • Half-Open (medio abierto): Tras un tiempo en estado Open, el componente pase a Half-Open, lo que indica que puede recibir una peque帽a cantidad de solicitudes para validar si el servicio est谩 nuevamente activo. Si las solicitudes pasan exitosamente, el componente pasa a Closed, en otro caso, regresa a Open.

Circuit Breaker pattern life cycle

 

Entornos As铆ncronos

Hasta este punto hemos analizado como es que este patr贸n se utiliza para servicios donde las invocaciones son s铆ncronas, pero 驴qu茅 pasar铆a si pasamos a un entorno donde los servicios a consumir se ejecutan de forma as铆ncrona? Por suerte, este patr贸n tambi茅n se puede utilizar bajo estas circunstancias, aun que debemos de cambiar un poco la l贸gica, aunque el principio es el mismo.

En entornos s铆ncronos, no tendremos respuestas con error ni timeout, por lo que las m茅tricas que utiliz谩bamos anteriormente no aplican, es por ello que podemos utilizar Colas (Queues):

Circuit Breaker pattern life cycle asincrono

 

En este caso, el Circuit Breaker en lugar de ejecutar directamente el servicio, tendr谩 que depositarlo en una Queue, de tal forma que el Supplier los podr谩 ir tomando a como pueda, lo que impide que lo saturemos de peticiones y lo hagamos colapsar, por otro lado, el Circuit Breaker podr谩 determinar el n煤mero de mensajes que tiene la Queue, y si este alcanza un umbral determinado, podr铆amos determinar que est谩 fallando o que est谩 procesando los mensajes demasiado lento, por lo que abrimos el circuito para impedir que se sature.

Como vemos, el funcionamiento es el mismo, lo que cambia es la forma de medir si un servicio est谩 fallando o tarda mucho tiempo en procesar los mensajes.

 

驴Te gustar铆a aprender m谩s patrones como este? te invito a que veas mi libro “Introducci贸n a los patrones de dise帽o” el 煤nico libro que te ense帽a los principales patrones de dise帽o utilizando ejemplos del mundo real. Olv铆date de aprender con los ejemplos t铆picos de internet como, crear una pizza, animales que ladren o figuras geom茅tricas.

 

Ventajas de implementar Circuit Breaker

Adicional a las ventajas obvias que podemos ver, como la tolerancia a fallas y el env铆o de solicitudes a servicios que sabemos que van a fallar, existen otros tipos de ventajas:

 

Monitoreo:

Dado que tenemos un componente que su 煤nica funcionalidad es sondear el estado de vida de los servicios, es posible tener un monitoreo en tiempo real, que nos indique los tiempos de respuesta promedio, frecuencia de falla, estado actual del servicio y, sobre todo, notificaciones en tiempo real si alg煤n servicio comienza a fallar.

 

Sobrecarga:

La capacidad de abrir el circuito ante un error o Timeout que sabemos que va a pasar, nos ahorra el hecho de tener muchos hilos esperando a que el servicio responda, y m谩s a煤n, si tenemos miles de usuarios, es probable tener much铆simos hilos detenidos, lo que provocar铆a que nuestro sistema se sobre cargue, incluso, puede provocar una bola de nieve que comience a afectar a otros componentes.

 

Tolerancia a fallas

Como ya lo dijimos, el Circuit Breaker puede redireccionar la petici贸n al siguiente Supplier en caso de que alguno falle, evitando tener que enviarle el error al cliente.

 

 

Conclusiones

Como hemos analizado a lo largo de este art铆culo, utilizar el patr贸n Circuit Breaker permite que inundemos nuestra aplicaci贸n con una gran cantidad de solicitudes que sabemos de antemano que van a fallar, por lo que, en lugar de eso, re direccionamos las peticiones a una instancia del servicio que est谩 operativo.

Este patr贸n de dise帽o es altamente utilizado en entornos distribuidos y con arquitecturas de microservicios, por lo que no es para nada recomendable utilizarlo para operaciones en memoria o servicios albergados de forma local. Recordemos que este patr贸n est谩 dise帽ado para recursos remotos.

 

Deja un comentario

Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *