Arquitectura basada en microservicios y su importancia en el desarrollo de software Ejemplo práctico: procedimiento para el desarrollo de una aplicación orientada a microservicios utilizando grails framework Eduardo Hernández Gutiérrez, Eduardo Cornejo Velázquez Universidad Autónoma del Estado de Hidalgo Pachuca de Soto, Hidalgo, México Email: {eduardo_hernandez, ecornejo} @uaeh.edu.mx Resumen — En En el presente artículo se expone la importancia que tiene hoy día el desarrollo de sistemas basados en microservicios y las diferencias que tienen éstos con respecto a los sistemas tradicionales basados en arquitecturas monolíticas. También, a manera de ejemplo se hace mención de un procedimiento para la construcción de aplicaciones Web basadas en una arquitectura de microservicios que se aplica específicamente al desarrollo con Grails Framework y que surge como resultado de la experiencia que los autores de este documento han adquirido luego de la adopción de técnicas, herramientas y metodologías del movimiento ‘agile’ el cual tiene como objetivo principal establecer las directrices y buenas practicas que desembocan en el desarrollo de software más estable, ágil y eficiente. Palabras clave web services, REST, grails, arquitectura — web basada en en mi cr oser oser vicios, vi cios, sistemas monol í ti cos.
I. I NTRODUCCIÓN Cuando una organización comienza a presentar un crecimiento en componentes clave tales como: su nómina, infraestructura física, clientes y los servicios que se ofrecen a éstos últimos. La infraestructura tecnológica y en especial los sistemas de información se ven afectados de manera directa debido al incremento en el número de transacciones y requerimientos que los usuarios exigen día a día.
se despliega como un archivo WAR (en el caso de las aplicaciones Web). El problema: la más mínima modificación implica detener la aplicación en su totalidad aun cuando algunas partes de ésta no necesariamente dependan de otras, pero igual igual están encapsuladas encapsuladas en el mismo aplicativo aplicativo [8]. [8]. La solución que eventualmente surgió: desarrollo de sistemas basados en una arquitectura de microservicios que siguen manteniendo el patrón de diseño MVC. Esto representó un nuevo enfoque que revolucionó la forma en que se desarrolla el software actualmente. A través de la modularización de los requerimientos de un producto de software, es decir, el desarrollo de módulos independientes con funcionalidades o tareas específicas y que son consumidos por un cliente principal es posible crear soluciones eficientes y descentralizadas. II. SISTEMAS MONOLÍTICOS
En este escenario, es muy común que se soliciten nuevas funcionalidades y/o adecuaciones a los sistemas existentes por lo que es necesario que los equipos de desarrollo de software realicen cambios en la estructura (código) de dichas aplicaciones. Esto, no siempre resulta ser una tarea simple aun cuando los cambios pareciesen ser mínimos. Mucho tienen que ver el patrón arquitectural bajo el cual fue concebida la aplicación, el lenguaje de programación, la documentación existente y sobre todo, si los desarrolladores de aquel entonces siguen formado parte de la organización. Hasta hace pocos años, la mayoría de los sistemas empresariales eran desarrollados siguiendo una arquitecta monolítica y bajo el patrón de diseño modelo-vista-controlador o MVC y a través de los cuales se obtenían soluciones sólidas y funcionales salvo un único inconveniente, la aplicación resultante se instala como un único programa especializado o
Fig. 1 Arquitectura de 3 capas Fuente: Elaboración propia
A. Definición
Un sistema o aplicación monolítica es aquella que se construye como una única unidad. Actualmente este tipo de aplicaciones también se apoyan en el uso del patrón MVC (figura 1) para su construcción por lo que al final se tiene un sistema que internamente encapsula tres componentes básicos: como la interfaz de usuario y que consiste normalmente en páginas HTML/JavaScript que se ejecutan en el navegador del usuario.
La capa de presentación presentada
que contiene la lógica de negocio sobre un servidor de aplicaciones (operaciones y procedimientos). La capa lógica
La capa de datos que
se encarga de la conexión y acceso con las bases de datos y los cuales son utilizados por la capa lógica.
Una interacción de estás tres capas se da cuando el servidor en el que reside la capa lógica recibe las instrucciones o solicitudes HTTP enviadas por el navegador, ejecuta las instrucciones pertinentes, recupera y actualiza los datos de la base de datos en caso de ser necesario para finalmente generar o actualizar las vistas HTML que son presentadas al usuario por medio del navegador web. En la figura 2 se muestra la arquitectura básica de un sistema monolítico.
Simples de desplegar. Basta con instalar la aplicación (en el caso de aplicaciones de escritorio) o desplegarla a través de un servidor de aplicaciones si se trata de una aplicación Web. Fácil de escalar por medio de réplicas en nuevos servidores.
C. Desventajas
La necesidad de eventuales modificaciones implican tener que detener toda la aplicación. El equipo de desarrollo debe estar presente en cada proceso que implique la realización de cambios a la aplicación en caso de alguna eventualidad crítica. En este tipo de aplicaciones, al haber una interdependencia de recursos es muy probable que el más mínimo cambio afecte a otras partes. III. ARQUITECTURA BASADA EN MICROSERVICIOS
A. Definición
Los microservicios son una arquitectura basada en pequeños y autónomos servicios que trabajan de forma conjunta los cuales surgen como una alternativa a las aplicaciones monolíticas en donde todos los servicios estaban contenidos en la misma aplicación y desplegados en todos los servidores [9]. Martin Fowler y James Lewis [6] definen un microservicio como un estilo arquitectural, es decir, una forma de desarrollar una aplicación, basada en un conjunto de pequeños servicios, cada uno corriendo o ejecutando sus propios procesos y comunicándose mediante mecanismos livianos, generalmente un recurso API de HTTP.
Fig. 2 Arquitectura monolítica Fuente: Elaboración propia
B. Ventajas
Simple de desarrollar al tener un único ciclo de vida que va desde el análisis de requerimientos hasta la puesta en producción. Simple de probar ya que las pruebas unitarias solo se tiene que aplicar sobre una única aplicación.
Fig. 3 Arquitectura con microservicios Fuente: Elaboración propia
La arquitectura basada en microservicios propone que tanto la interfaz como las aplicaciones de usuario sean clientes de una colección de servicios. De esta forma se propicia en la medida de lo posible, que ninguna parte dependa necesariamente de otras partes, pudiendo así poder responder cada una ante cualquier situación. La figura 3 muestra de forma gráfica la arquitectura de las aplicaciones basadas en microservicios. B. Ventajas
Al trabajar con servicios como los basados en la arquitectura REST, puede haber más de un equipo de desarrollo ya que la plataforma de desarrollo y los lenguajes de programación no representan inconveniente alguno al momento de integrar cada módulo. Trabajar por separado cada módulo facilita realizar modificaciones a funcionalidades específicas de la aplicación sin tener que detener el servicio por completo. A diferencia de los sistemas monolíticos, el escalamiento se hace a nivel de módulos o servicios lo cual reduce los costes en infraestructura tecnológica.
C. Desventajas
El despliegue. Al estar distribuidos en diferentes servidores y estar escritos en diferentes lenguajes implica la gestión de cada una de éstas tecnologías. El problema del versionado. Cada grupo de desarrollo debe encargarse de actualizar la documentación correspondiente. Redundancia e inconsistencia de datos. Producto de los cambios aplicados a algún modulo en particular y no generar la documentación correspondiente es posible que dos más de un módulo generen inconsistencias en la información procesada.
IV. E NTONCES ¿EN QUÉ CASOS ES CONVENIENTE DESARROLLAR APLICACIONES BASADAS EN MICROSERVICIOS ? Actualmente nos encontramos en una era en la que la integración de plataformas y sistemas están a orden del día, ésta, la denominada “la era de los servicios” [1] ha cambiado la forma en que se construyen las aplicaciones mediante el establecimiento de patrones arquitecturales basados en microservicios que buscan generar productos más estables, ágiles y eficientes. Decidir si es conveniente o no la implementación de los microservicios en nuestros proyectos de desarrollo de software va a depender de las características del mismo los alcances esperados. No por nada es que existen un incontable número de técnicas, patrones de diseño y arquitectural que han ofrecido a más de uno la solución más acorde a sus necesidades. Tal como menciona [8], una arquitectura basada en microservicios
no es intrínsecamente más costosa de desarrollar que una monolítica, solo requiere de un conjunto de competencias diferentes que algunos desarrolladores aún no han adquirido, además, siempre se deben plantear soluciones que entes orientados a cumplir los objetivos de negocio de la empresa a corto y largo plazo. V. EJEMPLO : PROCEDIMIENTO PARA EL DESARROLLO DE UNA APLICACIÓN ORIENTADA A MICROSERVICIOS UTILIZANDO GRAILS FRAMEWORK
Grails Framework
Grails es un framework creado por Graeme Rocher en el año 2006 como una respuesta a la necesidad de agilizar, automatizar y simplificar el desarrollo de aplicaciones Web que trabaja sobre la filosofía DRY: Don’ t repeat yourself! [2]. Grails se basa en el uso del lenguaje de Java, mediante la implementación de Groovy, además de que internamente implementa técnicas y tecnologías ya existentes de Java como Srping e Hibernate. El resultado es un framework que ofrece estabilidad al implementar tecnologías ya conocidas y librando al desarrollador de la tediosa y complicada tarea de configuración ya que Grails lo hace de forma automática en la mayoría de los casos. REST en Grails
Por defecto Grails permite la generación de proyectos basados en el patrón arquitectural de tipo REST [12], el cual hace uso de XML y JSON como medio de comunicación y combinándolo con los métodos HTTP. A continuación se describe de manera muy superficial el procedimiento que ejemplifica el desarrollo de una aplicación basada en servicios con grails, si el lector desea verificar su funcionalidad y aplicarlo a un proyecto propio puede acceder a repositorio de GitHub en https://github.com/lalo9210/grailsTutoWebServices y revisar el tutorial completo aplicado a un proyecto real. Este procedimiento puede ser de gran utilidad para aquellos desarrolladores que se inician en el uso de web services con grails. Es importante mencionar que el procedimental es resultado de la experiencia que los autores de este documento han adquirido con el paso del tiempo por lo que en ningún momento supone un estándar a seguir y es susceptible a mejoras. A. Creación del proyecto y definición del modelo de datos
1. Definición de módulos Para poder comenzar el desarrollo del sistema es necesario tener claro cada uno de los módulos y las funcionalidades que les corresponden tratando de no duplicar trabajo. 2. Generar el proyecto en Grails 3. Crear las clases de dominio Según las convencionalidades de Grails, cada una de las clases de dominio se mapea directamente con una tabla en la base de datos, si no existe se crea al momento de
ejecutar la aplicación, sin embargo, también es posible que se desee utilizar alguna base de datos y/o tablas existentes, para tal efecto, el desarrollador deberá hacer las configuraciones pertinentes. 4. Definir los atributos y las restricciones Al igual que con las clases de dominio, cada atributo representa a un elemento determinado en la base de datos, en este caso, las columnas de cada tabla asociada con la clase de dominio. Es posible establecer desde la clase de dominio el tipo de dato y restricciones que cada columna en la base de datos deberá tener. 5. Generar las pruebas unitarias para los atributos de las clases de dominio y sus restricciones En cualquier proyecto de desarrollo de software es indispensable no pasar por alto la generación de las pruebas unitarias para cada uno de los componentes que se van generando a medida que el proyecto avanza, el objetivo de las pruebas unitarias consiste en evaluar el correcto funcionamiento de cada artefacto generado incluso antes de tener una interfaz gráfica, esto de alguna manera permite detectar errores antes de la puesta en marcha del primer prototipo funcional. B. Definición de servicios
6. Agregar una clase abstracta “Service” El uso de clases abstractas permite definir aquellos métodos que son comunes e invariantes por los objetos generados en el proyecto, por ejemplo, en un sistema no pueden faltar las operaciones básicas del CRUD para el manejo de la información. En este caso, se puede definir una clase abstracta que se encargue de ello y posteriormente ir extendiendo las funcionalidades de la misma según lo requieran las clases que de ella hereden. 7. Crear las clases de “NombreDominioService” que extienden de la clase abstracta “Service”
En estos artefactos de debe especificar todas aquellos métodos y procedimientos especificados dentro de la lógica de negocios. 8. Crear las clases “Utils” para cada clase de dominio Estos archivos son muy importantes ya que nos permiten generar instancias temporales de las clases de dominio al momento de realizar las pruebas unitarias sin la necesidad de tener una base de datos y poder de esta manera comprobar la funcionalidad de los servicios generados hasta el momento. 9. Crear test unitarios para las clases de servicios C. Generación de controladores
Tal como lo establecen las directrices de la arquitectura MVC, los controladores deben fungir como artefactos que controlar las llamadas a operaciones y procedimientos almacenados en la capa lógica de la aplicación evitando. Con este procedimiento propuesto se busca lograr que los controladores únicamente sirvan como artefactos de
comunicación entre las peticiones del cliente y los servicios definidos. 10. Crear un controlador abstracto 11. Crear los controladores correspondientes a cada clase de dominio que extiendan del controlador abstracto 12. Desarrollo de pruebas o tests unitarios para los controladores D. Desarrollo del cliente
El desarrollo del cliente queda totalmente a libertad del programador, ya que es en este punto donde la integración de plataformas queda en evidencia. Tanto la plataforma de desarrollo y el lenguaje de programación no deben ser un impedimento para consumir los servicios generados por la aplicación desarrollada en Grails ya que son de tipo REST. Cada lenguaje y/o framework de desarrollo mantienen procedimientos y herramientas específicas para el desarrollo de clientes REST que quedan fuera del alcance de este documento y del tutorial ofrecido en el repositorio de GitHub. VI. R ESULTADOS (VENTAJAS OPERATIVAS) El procedimiento para el desarrollo de aplicaciones basadas en microservicios con grails que ha sido presentado a manera de ejemplo en este documento es actualmente aplicado por los autores de este documento en los proyectos de desarrollo de software que tienen a su cargo. El desarrollo de software basado en microservicios junto con la combinación de técnicas y metodologías ágiles han significado un cambio en las formas de trabajo ya que ahora en lugar de esperar varios meses para tener un primer prototipo funcional como ocurría con el desarrollo de sistemas monolíticos se ha optado por un desarrollo modular mediante una priorización previa de requerimientos y funcionalidades. De este modo se cumple con aquello que es importante y urgente, a la vez que se ponen a prueba dichos componentes en un escenario real y se genera la retroalimentación correspondiente por parte de los usuarios mientras el equipo de desarrollo se enfoca en la construcción de los siguientes módulos correspondientes. Como parte de los resultados obtenidos, a continuación se hace mención de las ventajas operativas que se han identificado en los diversos proyectos desarrollados con la arquitectura basada en microservicios. 1. Tomar la decisión de crear aplicaciones basadas en microservicios antes de pensar en aplicaciones monolíticas significa adelantarse al futuro. Si de antemano se tiene conciencia de que la aplicación crecerá de forma gradual a lo largo del tiempo y que la lógica de negocios se pueda ver forzada a cambiar constantemente, resulta más apropiado un desarrollo modular que además permite el desarrollo de servicios de una manera más rápida, fácil de entender y fácil de mantener. Así, cuanto más grande es la aplicación, más fácil resulta realizar cualquier cambio sin afectar la totalidad del sistema. 2.
Esta arquitectura permite que un equipo de desarrollo se pueda enfocar en el desarrollo de un servicio o
módulo de forma independiente. Con esto se permite además que los desarrolladores puedan escoger el tipo de tecnología para con la cual levarán a cabo su trabajo puesto, que al final se tienen microservicios basados en una arquitectura estándar como lo es REST. 3. La arquitectura basada en microservicios permite que cada servicio pueda ser desplegado de manera independiente lo cual permite a los desarrolladores poder hacer cualquier modificación sin que ello conlleve a la interrupción de las actividades de otro equipo de desarrollo o que se vea afectado el sistema en su totalidad. 4. Cuanto más grande es el número de peticiones y consumo de los servicios de un sistema, resulta más económico poder realizar el escalamiento de la aplicación, ya que, a diferencia de los que ocurre con los sistemas monolíticos en los que es necesario replicar todo el sistema en distintos servidores aun cuando los servicios que se están consumiendo mayormente son muy pocos, los sistemas basados en microservicios permiten desplegar el número exacto de instancias de un único servicio evitando así el uso excesivo de hardware y minimizando los costos del mismo. 5. Por último. Una de las principales ventajas que brinda el trabajar con sistemas basados en microservicios reside en la posibilidad de tener un único backend que funge como el núcleo base que es capaz alimentar de una gran variedad de productos finales (aplicaciones y/o sistemas) que solucionen las necesidades específicas de cada tipo de usuario final sin importar el sistema operativo, el lenguaje de programación o el dispositivo electrónico desde el que se accede a la información (figura 4). Al generar servicios universales que mantengan bien definidos sus procesos dentro de la lógica de negocio se evita la duplicidad de procesos e información.
Fig. 4 Integración de plataformas Fuente: Elaboración propia
VII. CONCLUSIONES Hoy día es cada vez más común que los sistemas de software no sean concebidos como herramientas que trabajan de forma individual. Actualmente, la mayoría de los sistemas hacen uso de recursos (información y procedimientos) provenientes de otros sistemas ya sean internos o externos a la organización misma y viceversa. Anteriormente, pensar en este tipo de interacción entre los sistemas resultaba sino improbable muy conflictivo debido a las diversas plataformas y lenguajes de desarrollo existentes. En el escenario más simple, la interacción entre un sistema de escritorio y uno desarrollado para web era imposible de concebirse. Con la llegada, o mejor dicho la estandarización de REST como un estilo de arquitectura que permitió la comunicación e integración de plataformas mediante el uso de servicios web, un nuevo paradigma en el ámbito de la programación y desarrollo de software surgió, a tal punto que ahora nos encontramos en la era de los servicios. Aun cuando el procedimiento propuesto está orientada al uso de Grails, este documento tiene un enfoque teórico que puede ser de gran utilidad para aquellos desarrolladores desean iniciar y entender los conceptos básicos del desarrollo de software orientado a microservicios. Para un desarrollador de software entender conceptos nuevos y adoptar una nueva forma de trabajo siempre resulta hasta cierto punto difícil, no tanto por la cuestión teórica, sino más bien por el hecho de aprender y aplicar de forma correcta las llamadas “buenas prácticas de programación”.
R EFERENCIAS [1] Alzate Sandoval, G. (2014). API's, Construyendo una nueva era. SG Software Guru #45, 18-19. [2] Brito, N, (2009). Manual de desarrollo Web con Grails. Madrid, España: Ediciones agiles. [3] Brown, J. S., & Rocher, G. (2013). The Definitive Guide to Grails 2. New York: Apress. [4] Cervantes, H. (2014). Las Interfaces y la Arquitectura. SG Software Guru #45, 24-25. [5] Hernández Gutiérrez, E. (2013). Sistema de Geolocalización de Espacios Universitarios en la UAEH (tesis de pregrado). Universidad Autónoma del Estado de Hidalgo. Pachuca de Soto, México. [6] Lewis, J., & Fowler, M. (25 de Marzo de 2014). Microservices. Obtenido de http://martinfowler.com/articles/microservices.html [7] Luna, V., & Arana, F. (Noviembre de 2014). TDD y Clean Code. SG Software Guru #46, 34-35. [8] Montoro, S. (12 de Julio de 2014). Microservicios | La pastilla roja. http://lapastillaroja.net/2014/07/microservicios/ [9] Newman, S. (2015). Building Microservices. United States of America: O'REILLY. [10] Sánchez, J. (Noviembre de 2014). ¿Por qué documentar el Código? SG Software Guru #46, 41. [11] Smith, G., & Ledbrook, P. (2014). Grails in Action second edition. Shelter Island, NY: Manning Publications Co. [12] Bernhardt, S. (Octubre de 2014). Microservices Architectures, Thougths from a SOA perspective. SOA Magazine, 22. [13] Thomas Fielding, R. (2000). Architectural Styles and the Design of Network-based Software Architectures. Obtenido de https://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm