Aplicación monolítica o distribuida?

En los últimos tiempos, hemos escuchado muchas opiniones sobre cómo es conveniente diseñar nuestras aplicaciones, desde el punto de vista de su arquitectura en la ejecución.  Históricamente las aplicaciones eran monolíticas (una aplicación que se instalaba en una computadora y hacia todo lo que necesitaba) y en forma más recientes se esta optando por hacer aplicaciones distribuidas en varias computadoras, dividas en servicios independientes (algunos lo llaman microservicios).

Al ser tan variadas las aplicaciones que realizamos, es claro que no hay una solución optima para todos los casos, sino que tenemos que adoptar (y adaptar) la arquitectura que mas nos convenga para cada caso.

También hay que entender que entre una aplicación monolítica y una aplicación totalmente basada en microservicios hay una gran variedad de combinaciones posibles, pues no hay que hacer binaria la elección.

El problema. 

Es una realidad, que los sistemas de información cada día abarcan más actividades de los negocios y la vida de los humanos, y por lo tanto tienden a crecer y hacerse complejos.  Cuando crecen en forma monolítica en una única aplicación, llega un momento que tiene un tamaño tan grande que nadie puede comprenderlos en su totalidad. Esto es un gran problema, pues al no comprenderlos del todo, cambiarlos generalmente trae consecuencias no deseadas o no planeadas.

Para llevarlo a ejemplos prácticos, es imposible para una persona comprender una KB Genexus con 10.000 objetos. Es demasiado grande, tiene tantas tablas que se hace imposible entender las relaciones entre ellas.

¿Que es lo que hacemos los ingenieros cuando tenemos un problema que es tan grande (o difícil) que no podemos resolverlo?
Generalmente usamos la técnica de Divide&Conquer, dividiendo el problema en problemas más chicos que puedan ser entendidos y optimizados en forma más fácil. Una forma de dividir el problema, es dividir la aplicación en servicios más chicos y con eso llegamos a la arquitectura de microservicios.

También es conocido, que el tener óptimos en los problemas chicos, muchas veces no termina siendo el óptimo global. Por ejemplo, puedo tener un servicio que sea extremadamente rapido y funcione siempre bien, pero resulta complicado de programar para ser consumido por el resto de la aplicación.

Evaluando opciones


Voy a hacer una comparación sencilla de una arquitectura monolítica y una arquitectura de microservicios, viendo sus beneficios y sus desventajas. 

Beneficios de una arquitectura monolítica



  • Sencilla de desarrollar. 
  • No hay que pensar demasiado donde desarrollo una nueva funcionalidad. Todo se programa en la misma KB.



  • Sencilla de instalar. 
  • Se instala todo junto en una misma instalación.



  • Sencilla de escalar. 
  • Si necesito mas potencia, puedo replicar una máquina que ya tiene la aplicación funcionando y si me aseguro que un usuario siempre es atendido por un servidor durante toda su sesión, no tendría grandes problemas.



  • Fácil de monitorear
  • Al tener todo concentrado en una única aplicación, es sencillo encontrar cual es la parte que está teniendo problemas, pues todo está centralizado.



  • Testeo funcional es mas fácil.
  • Como todo esta concentrado en una aplicación, si la pruebo, ya pruebo que todo funciona bien.

    Desventajas de la aplicación monolítica. 



  • Tamaño y complejidad limitadas. 

  • Las aplicaciones crecen a tal punto que por su tamaño y complejidad son difíciles de entender y los cambios no pueden ser hechos en forma correcta y rápida.
    El desconocimiento (o mal entendimiento) de la aplicación produce miedo que los cambios afecten a la aplicación y por lo tanto se realizan muchas tareas de testing manual con cada liberación.

    El tamaño de la instalación puede hacer lento la instalación / build all / etc. enlenteciendo el desarrollo y dificultando el uso de DevOps.



  • Fiabilidad de la aplicación. 

  • Un problema de performance o consumo desmedido de recursos (memoria, lecturas en disco, bloqueos en la base de datos, sentencias lentas) puede dejar a toda la aplicación fuera de servicio.



  • Innovación tecnológica. 

  • Al ser una aplicación monolítica, es mas difícil hacer innovaciones tecnologicas.
    Por ejemplo, si hay que cambiar la base de datos, hay que hacerlo para toda la aplicación.
    Si hay que cambiar instalar una versión nueva de GeneXus, hay que hacerlo para toda la KB y no se puede hacer en forma escalonada. Las tareas de build/pack/deploy/test llevan mucho tiempo y conllevan un gran riesgo porque es difícil garantizar que todo va a funcionar bien en la nueva versión.

    Beneficios de los microservicios. 



  • Fáciles de entender. 
  • Al atacar problemas mas chicos, los servicios son mas fáciles de entender, por lo tanto de desarrollar y de mantener.



  • Independencia entre servicios. 
  • Es posible desarrollar cada uno de los servicios en forma independiente (siempre que mantengan y respeten las interfaces que publican).
    Esto da muchísimas ventajas en la elección de que herramientas utilizar para el desarrollo, permite crear grupos mas chicos de desarrolladores, hacer cambios tecnologicos mas rapido.
    Además cada servicio puede ser optimizado y escalado en forma independiente de los demás, posibilitando un buen uso de los recursos existentes. 

    Desventajas de los microservicios


  • Complejidad de la arquitectura. 
  • Al tener servicios independientes, vamos a tener que elegir de que forma van a conectarse dichos servicios, con comunicaciones entre procesos (rest, soap, otros) haciendo que la arquitectura quede bastante complicada.


  • Múltiples base de datos
  • Si cada servicio es independiente de los demás, vamos a tener diferentes bases de datos para cada servicio. Esto trae problemas de varios tipos, como pueden ser problemas de performance para leer datos que estén en diferentes servicios. Como cada servicio se encarga solo de la integridad de sus datos, el manejo de transacciones que afecten mas de un servicio, es responsabilidad de la aplicación (y no de la base de datos) agregando complejidad a la misma. 


  • Más complejo de probar. 
  • Si bien la prueba unitaria dentro de cada servicio es más fácil, la prueba de la aplicación basada en microservicios es bastante más compleja y necesita de mucha más coordinación y programación. 


  • Manejo de requerimientos
  • Cuando se tiene un cambio que involucra a muchos servicios, los mismos deben realizarse en forma coordinada y la instalación también debe hacerse en forma coordinada, agregando costos al proceso de instalación.


  • Instalación compleja. 
  • Al tener muchos servicios, es necesario tener automatizado el proceso pues si no se vuelve inmanejable. Además es mucho mas difícil el saber en que version esta la aplicacion, pues todos los componentes evolucionan en forma independiente, haciendo que la detección y reproducción de los problemas sea una tarea compleja. 

    Conclusiones

    No me animo a sacar conclusiones categóricas en este tema. 

    Lo mejor sería contar con herramientas que nos permitan manejar grandes problemas que tengan las cosas buenas de las aplicaciones monolíticas y las cosas buenas de los microservicios, y con pocas de las desventajas de ambas arquitecturas. 


    En el caso de GeneXus, creo que lo mejor que podemos aspirar hoy es a tener una gran KB, que tenga toda la aplicación y dividida en módulos. En el futuro, me gustaría que dichos módulos puedan instalarse en forma independiente, desarrollarse con diferentes generadores y poder manejar la interfaz de los módulos en forma explícita. 

    Por ejemplo, sería bueno poder tener una aplicación que tenga el módulo de contabilidad en GX16, pero el modulo de facturacion en GX17, todo usando la misma base de conocimiento, y que los problemas de la integración sean resueltos por GeneXus.  La base de datos seria centralizada, asi como su reorganización y manejo. 

    También estaría bueno que las tablas de la aplicación estuvieran separadas por módulos, para hacer un poco más fácil entender el esquema de la misma. 

    Si tenemos herramientas que garantizan que no se cambio la interfaz de un módulo, tendríamos la tranquilidad de poder instalar sin afectar a otros módulos. 
    También sería importante tener una forma de desarrollar dentro del IDE, que solo muestre los objetos de un módulo y los objetos públicos de otros módulos, simplificando le proceso de entender cómo funciona dicho modulo.  

    Queda bastante por hacer, pero creo que seria una buena forma de generar aplicaciones con un desarrollo monolítico, de instalación ágil y distribuida que concentre lo mejor de los dos mundos, automatizando gran parte del proceso. 

    Comentarios

    1. Excelente artículo Enrique. Se comprende con mucha simplicidad los comparativos entre microservicios y monolítico. Cualquier acción sobre una Kb grande, es compleja.
      Gracias.

      ResponderEliminar
    2. Estos son los temas que deberían marcar la agenda del mundo GeneXus, me he tenido que enfrentar al problema de que arquitectura llevar adelante. De todas formas creo que se le tendría que dar mas prioridad a los módulos ya que para nosotros sería una ayuda para mejorar nuestro trabajo. Lamentablemente la agenda la marcan los cambios tecnológicos y las cosas importantes en ocasiones quedan para atrás. En resumen creo que lo único que podemos ir haciendo es trabajar con los módulos.

      ResponderEliminar
      Respuestas
      1. Gracias Urulinux. Creo que los módulos tienen ya casi todas las funcionalidades que se necesitan, pero ahora falta que GeneXus use dicha potencia, facilitando ver en forma parcial en un módulo y los objetos públicos.

        Eliminar

    Publicar un comentario

    1) Lee el post
    2) Poné tu opinión sobre el mismo.
    Todos los comentarios serán leidos y la mayoría son publicados.

    Entradas más populares de este blog

    Paleta de colores en GeneXus

    Acceder a los header SOAP en programas GeneXus