Aplicaciones distribuidas con ZeroMQ (I)

Como profesionales de sistemas es una buena costumbre detenernos a pensar sobre algunos aspectos arquitectónicos de las aplicaciones que desarrollamos.

Los sistemas de información actuales son cada vez más grandes y complejos, y están construidos sobre una gran cantidad de componentes interrelacionados de las maneras más inverosímiles que podamos imaginarnos. Muchas veces esta complejidad reside en el hecho de que las aplicaciones fueron concebidas como un cuerpo monolítico y que con el tiempo crecieron anárquicamente para soportar escenarios inicialmente no considerados, casi sin tener una visión global del problema al que dan solución.

La desventaja de los sistemas así concebidos es que se tornan difíciles de mantener y llega un punto en que parece que lo único que podemos hacer es escalar en hardware hasta llegar al colapso. Este crecimiento exponencial de la complejidad se traslada a todas las actividades de la Ingeniería de Software. A modo de ejemplo podemos citar algunas actividades que se ven afectadas de manera negativa: es más complicado gestionar las requerimientos no funcionales, es más dificultoso manejar de manera adecuada las dependencias del sistema, los ciclos de pruebas son cada vez más largos, es necesario un conocimiento más detallado de todo el sistema para poder modificarlo, entre otras.

Otro punto importante en contra de los sistemas monolíticos es que, de cierta forma, ya no es posible optar por otras tecnologías que podrían ser más adecuadas para solucionar los nuevos problemas, ya que el sistema queda atado a las inicialmente escogidas o bien es muy costoso integrarlas en el monolito.

De esta manera, gracias a la creciente omnipresencia de las TIC e Internet, las aplicaciones distribuidas surgieron como una evolución natural y necesaria frente a las limitaciones impuestas por los sistemas tradicionalmente monolíticos. Y casi sin darnos cuenta hoy en día la mayoría de los grandes sistemas empresariales se empezaron a pensar como sistemas distribuidos.

Sistemas distribuidos

Un sistema distribuido es aquél que fragmenta sus principales funciones y las distribuye en distintos componente autónomos interconectados por una red. Dichos componentes pueden ser heterogéneos, es decir, que pueden correr en entornos de ejecución separados e incluso estar desarrollados en plataformas y lenguajes de programación completamente diferentes, pero tienen la capacidad de coordinarse y cooperar para darle al usuario —personas u otros sistemas— la sensación de constituir un único sistema coherente.

Por eso en entornos distribuidos es de vital importancia el establecimiento de mecanismos estándares que regulen la interacción entre los distintos componentes implicados. Dichos protocolos de comunicación están por encima de las particularidades de cada plataforma, de modo que independientemente de su naturaleza, cualquier computadora pueda comunicarse con el resto.

Microservicios

Si bien actualmente es muy común que los sistemas estén diseñados en capas, suele pasar que el patrón Modelo-Vista-Controlador (MVC) no es suficiente para ciertas aplicaciones empresariales. Supongamos que una empresa adquiere sistemas ERP/CRM para llevar adelante su operatoria. Dicho sistema es perfectamente funcional y trabaja sin fisuras dentro de la corporación. Pero luego se descubre que para seguir creciendo es necesario integrar el sistema hacia la cadena productiva, es decir hacia los proveedores y los distribuidores. Así se vuelve necesario montar algún tipo de gestión de procesos de negocios (BPM) porque los servicios que perciben los usuarios no se pueden prestar sólo con el software que maneja uno de los departamentos. Los microservicios vienen a plantear una alternativa en este contexto.

Los microservicios son una manera muy interesante de implementar una arquitectura orientadas a servicios (SOA). Un microservicio es una pequeña aplicación que cumple una única función y la cual se comunica con otras pequeñas aplicaciones a través de un mecanismo común. Cada microservicio tiene una funcionalidad específica y bien definida la cual se implementa en relativamente pocas líneas de código y en un lenguaje de programación particular que no necesariamente tiene que ser el mismo para todos los microservicios. La clave está en el protocolo de comunicación y en la gestión de los mensajes a través de los cuales los microservicios colaboran.

La arquitectura basada en microservicios propone que tanto la interfaz (UI) como las aplicaciones de usuario sean clientes de una colección de servicios que operan cada uno sobre un dominio particular. A su vez proponen escalar las aplicaciones mediante una especie de sharding de código y datos.

Sistemas Monolíticos vs Microservicios
Sistemas Monolíticos vs Microservicios

No todo es color de rosa. Dividir una aplicación en servicios no es una tarea trivial. Los microservicios tienen su materia pendiente en la facilidad para el despliegue y en la gestión de versiones, y todavía hay mucha tela para cortar en este sentido. En ese nicho van creciendo herramientas para la generación y el mantenimiento de ambientes de ejecución heterogéneos, como Vagrant o Docker, que permiten replicar entorno de ejecución consistentes para microservicios implementados en diferentes tecnologías y que éstos convivan sin gastar toda la energía en ello. También el aprovechamiento de servidores de integración continua se vuelve una necesidad imperiosa en las arquitecturas de microservicios.

Pero quizá el problema más grave es el mantenimiento de la consistencia de datos replicados entre los dominios de diferentes servicios. En la mayoría de las arquitecturas basadas en microservicios los datos son sólo eventualmente consistentes, lo que significa que es posible que dos clientes que se ejecutan en paralelo reciban resultados diferentes. El mayor error de diseño que se puede encontrar hasta ahora en las aplicaciones basadas en servicios es montar la replicación de forma explícita y carecer de un buen mecanismo de consolidación de datos. Conviene recordar que evitar la redundancia y la inconsistencia de datos fueron las dos razones principales para diseñar en un principio aplicaciones monolíticas transaccionales.


En esta primera publicación se introdujeron algunos conceptos básicos de aplicaciones distribuidas y microservicios. En la siguiente publicación se abordarán diferentes aspectos técnicos de ZeroMQ, una librería de mensajería que permite comunicar microservicios de forma sencilla.

Get in Touch