Continuando con en el artículo anterior “Programación Reactiva (Reactive Programming)”, el día de hoy seguiremos explorando este modelo de programación de aplicaciones.
Si bien es cierto que la programación reactiva no es solo reaccionar a eventos para ganar escalabilidad, si es una de las características importantes en este modelo de programación. Pero ¿Por qué la necesidad de construir aplicaciones reactivas?
Pues bien, debemos tener en cuenta la evolución que se ha tenido de los requisitos no funcionales en la última década, pasamos de aplicaciones de cliente-servidor de escritorio a aplicaciones Web en internet que se manejan en granjas de servidores, con pocos segundos de respuesta, varias horas de tiempo off-line para mantenimientos y gestión de servidores, que manejan varias gigas de información y tiempos de latencia de segundos; pero ahora tenemos aplicaciones que se distribuyen e instalan en toda clase de dispositivos móviles accediendo una gran cantidad de servicios basados en la nube, como la de Amazon, Google y Windosw Azure entre otras, que poseen cientos y miles de núcleos de procesamiento, deben responder en milisegundos o microsegundos, con tiempos de latencia demasiado pequeños del orden de milisegundos, deben estar el 100% del tiempo de disponibles, administran teras o petabytes de almacenamiento de información y para acabar de ajustar con usuarios cada vez más exigentes y no están dispuestos a esperar.
Entonces, como nuevos requisitos requieren nuevas tecnologías, podemos expandir este concepto y definir que: nuevos requisitos no funcionales requieren nuevos modelos de arquitectura y nuevos modelos de programación; ahora, uno de estos nuevos modelos es la programación reactiva. El éxito de una aplicación reactiva es que responda fácilmente a un conjunto de estímulos, que sus componentes siempre estén activos y respondan activamente a estos. Las reacciones de una aplicación reactiva a un estímulo determinado se pueden clasificar en 4 grandes categorías:
*GRÁFICA 1: CARACTERÍSTICAS DE LAS APLICACIONES Y ARQUITECTURAS REACTIVAS
Reacción a eventos: es la capacidad que deben tener los componentes internos de la aplicación para comunicarse entre sí, desarrollando invocaciones asincrónicas de notificación de terminación de tareas o realizar una tarea basado en la suscripción a un tipo de especial de notificación o evento de otro componente.
Reacción a la carga: una aplicación reactiva debe reaccionar e implementar acciones dependiendo de la carga de procesamiento que tenga y así evitar episodios de contención en acceso a recursos o módulos compartidos, en otras palabras debe escalar adecuadamente al incremento de usuarios, transacciones y procesos.
Reacción a la falla: una buena aplicación reactiva debe poder implementar tolerancia a fallos y poder recuperarse de una falla en todos sus niveles de aplicación, es decir, debe ser un sistema altamente resiliente.
Reacción a los usuarios: Garantizar un tiempo de respuesta adecuado a los usuarios independientemente de la carga y entregarles a tiempo lo que ellos solicitan es respetarlo.
Cada una de las anteriores características es una característica importante en las aplicaciones y arquitecturas reactivas, debe haber un perfecto balance entre estas cuatro categorías para que la aplicación reactiva funcione adecuadamente y le entregue al usuario lo que él solicitó y en el menor tiempo posible.
A Continuación ahondaremos más en cada una de las características de las aplicaciones reactivas, específicamente en la resiliencia o la tolerancia a los fallos, y en los próximos artículos nos enfocaremos en las otras tres características de las aplicaciones y arquitecturas reactivas.
Resiliencia
Definición: La resiliencia en términos del desarrollo de software es la capacidad de un sistema o aplicación de tolerar, soportar, adaptarse y recuperarse ante desastres, fallas de hardware, infraestructura y comunicaciones; perturbaciones en los datos o flujos de trabajo de manera que la aplicación no quede en un estado inestable y por consiguiente estas fallas escalen hasta los usuarios y lleguen a molestarlos.
El tiempo off-line de una aplicación es uno de los principales problemas que enfrentan los negocios hoy día. Imagínense un banco con el sistema de transacciones off-line “caído” por algún daño en su canal de comunicaciones. ¿Cuánto dinero deja de recibir por la no operación?, ¿O una cadena de almacenes en la cual los clientes no puedan pagar con tarjetas de esa entidad bancaria?
O imaginemos también un portal de comercio electrónico que su base de datos esté fuera de línea.
Se ha incluido la palabra Resiliencia en los avances de la 23ª edición del Diccionario de la lengua española de la Real Academia Española.
El usuario no va a poder comprar los productos que necesitaba, se va a ver altamente perjudicado, va a demostrar su malestar y a la final esto es un irrespeto para él, la cadena de almacenes debe dar la cara al usuario por un problema que no es de ella y si esta situación si se vuelve recurrente puede desestabilizar una relación de negocios o terminarla.
Por el contrario, el hecho de que una aplicación pueda reaccionar a estos fallos o a un conjunto de potenciales puntos de quiebre es una gran ganancia y genera confianza en la aplicación y potencializa negocios.
Miremos un caso específico de reacción a un problema en un canal de comunicaciones, NetFlix.
El principal objetivo de NetFlix es la entrega del streaming solicitado por el usuario. En condiciones normales, la comunicación entre la aplicación de usuario final de NetFlix y los servidores de streaming fluye normalmente, tenemos un usuario con banda ancha de 4 Gigas y una granja de servidores de streaming dispuesta a entregar el streaming solicitado. Pero resulta que la velocidad de la conexión a internet el usuario decae, entonces la aplicación de NetFlix no puede seguir enviando los fotogramas del streaming en alta decisión porque tendría la posibilidad de interrumpir el streaming y así el usuario no puede seguir viendo su película, video, etc.
Para este tipo de problema, la aplicación de NetFlix continuamente está censando el canal de comunicación entre el usuario y los servidores de streaming y cuando detecta una caída en la velocidad de conexión a internet del usuario, la aplicación de NetFlix le dice a los servidores de streaming que ya no entreguen los fotogramas en alta definición, sino en una resolución más baja por el problema que se está experimentando. Como resultado final, el usuario puede notar o experimentar una disminución en la calidad del video, pero podrá seguir viendo su película y no se molestará.
La tolerancia a fallos en una aplicación reactiva debe darse en todos los niveles de la aplicación: infraestructura y canales de comunicación; bases de datos y transacciones; sistemas de autenticación y flujos de trabajo; servidor de aplicaciones y servicios, no es solo la tolerancia a fallos en hardware o comunicaciones como estamos acostumbrados a hacerlo.
Antes de iniciar a construir una aplicación reactiva debemos investigar y definir los posibles puntos de ruptura para poder incorporarlos en el diseño y tomar medidas. Se debe tener en cuenta que muchas soluciones que se dan para una tolerancia a fallos son herramientas instalas sobre los servidores. Una implementación de alta disponibilidad común y tradicional puede ser el servidor de aplicaciones en cluster, pero la conmutación por error entre servidores puede ser costosa y peligrosa hasta el punto de llegar a desencadenar una falla en cascada con terribles consecuencias.
Debemos establecer, en una aplicación resiliente, una granularidad adecuada en los componentes de modo que esta granularidad nos permita aislar un componente que falle y reemplazarlo por otra instancia debidamente aislada. Para lograr esta granularidad e implementación de este tipo de tolerancia a fallas debemos tener en cuenta el patrón bulkhead pattern. Este patrón arquitectónico nos permite tener componentes debidamente aislados y granulares, a nivel de procesos si lo queremos, y así evitar caídas en cascada que pueden llegar a afectar toda la aplicación completamente.