intive Argentina Blog

Rompiendo el monolito: Microservicios

El 28 de agosto asistí al .Net Meetup by DataArt, en el que charlaron sobre Microservicios con ASP.NET Core. Eso me motivó a que hoy les quiera contar sobre la definición y las características de los microservicios como arquitectura. La mayor parte de este artículo está inspirada en el de Martin Fowler: Microservices, del que sacamos algunas conclusiones.

El Monolito

Venimos trabajando de manera monolítica. En nuestras aplicaciones, lo más común es encontrarnos con una arquitectura por capas, en la cual tenemos una única base de código con múltiples módulos. Normalmente, está  la capa de UI, la de business logic, y la de data access. Si se hace un cambio en alguno de estos módulos, por más chico que sea, debemos redeployar la aplicación completa. De igual forma, sabemos que la escalabilidad se convierte en un reto, ya que todos los módulos deben ir a la par de manera horizontal para escalar el sistema completo, creando un riesgo de acoplamiento inherente a esta arquitectura. Por lo visto, se vuelve muy difícil cambiar la tecnología, lenguaje, o framework, ya que toda la aplicación está fuertemente acoplada y los componentes son dependientes entre sí.

Fuente – Arquitectura Monolítica

¿Qué son microservicios?

La arquitectura por microservicios viene dada por una colección de servicios vagamente acoplados, donde un proceso se divide en varios (microservicios) y cada uno debe tener solo una única responsabilidad.

Fuente – Arquitectura de Microservicios

 

A diferencia de las aplicaciones monolíticas, que deben escalar completas, desarrollar bajo la arquitectura de microservicios nos permite escalar cada microservicio independientemente. De esta manera, podemos cubrir la demanda o aumentar la funcionalidad de cada área que lo necesite, sin afectar a las demás. La composición de aplicaciones por microservicios permite mejorar la integración y entrega continua de paquetes, ya que podemos hacer deploy parcial de un servicio puntual. De igual manera, cada microservicio puede estar asilado bajo su propio entorno y tecnología que se adecue a la responsabilidad particular de este.

Fuente – Monolitos y Microservicios

 

Componentes organizados alrededor del negocio

Los componentes de los microservicios son reemplazables y actualizables independientemente. Usualmente al separar una gran aplicación en componentes, las empresas se enfocan en crear equipos con un esquema de desarrollo similar al organizacional (UI Teams, Server-side logic teams, database teams, etc.). Esto lo podemos ver como un ejemplo de la ley de Conway. Any organization that designs a system (defined broadly) will produce a design whose structure is a copy of the organization’s communication structure. — Melvyn Conway, 1967.

Fuente – La ley de Conway en acción

 

Al poseer una arquitectura molecular, los microservicios están organizados alrededor de la capacidad del negocio, donde cada equipo es interfuncional y se adecua a las destrezas necesarias para desarrollar cada funcionalidad por separado. Es por esto por lo que podemos ver equipos completos para cada área en particular (Órdenes, envíos, inventario…) al igual que los componentes asociados, como la interfaz de usuario, almacenamiento y el stack de software a implementar dentro de cada microservicio.

Fuente – Límites de servicio reforzados por limites de equipo

 

La mayor parte del esfuerzo para el desarrollo de aplicaciones que vemos hoy en día está orientada a proyectos, donde, una vez el software queda terminado y entregado, se transfiere a un equipo de mantenimiento y luego se disuelve el equipo original para ocuparse de otros proyectos. Por el contrario, cada microservicio es considerado un producto, con un equipo único que mantiene el ownership del mismo hasta haber finalizado su ciclo de vida completo.

Servicios Inteligentes, Comunicaciones Simples

La comunidad de desarrolladores de microservicios favorece un acercamiento a la estructura de comunicación entre microservicios, dada por Smart endpoints and dumb pipes, donde la meta es que las aplicaciones se mantengan lo más desacopladas y cohesivas posibles. Para esto se utilizan dos acercamientos.

  • Comunicación por protocolos HTTP request-response entre las APIs, siguiendo los principios y protocolos que se asemejan a cómo funciona Internet.
  • Mensajería liviana, utilizando implementaciones simples, como RabbitMQ o ZeroMQ y donde la lógica en que se producen y consumen mensajes se mantiene en los servicios.

Gestión y Datos Descentralizados

Mientras las aplicaciones monolíticas prefieren una única base de datos para garantizar la consistencia de la información, los microservicios prefieren tener una base de datos propia para cada servicio. Estas bases de datos pueden utilizar la misma tecnología o ser de una variedad de diferentes tecnologías de almacenamiento (Cassandra, MongoDB, SQLServer) para diferentes tipos de datos. A esta persistencia en los datos le llamamos Persistencia Políglota. Descentralizar la gestión de la data a través de los microservicios, implica que las actualizaciones a la base de datos se deben manejar de manera no transaccional, implementando una cola de mensajes o remote procedure calls (RPC).

Fuente – Data Descentralizada

 

Automatización de infraestructura

Los equipos que implementan la arquitectura de microservicios hacen uso extensivo de las herramientas de automatización, para lograr, junto a los DevOps, reducir la complejidad del build, deploy y operación de los microservicios. Entre ellas, Continuous Integration (CI) y posteriormente Continuous Delivery (CD) otorgan la posibilidad de mantener un sistema escalable, con pruebas automáticas y monitoreo/logging detallado. En los microservicios, el uso de containers como Docker nos permite hacer deploy de nuestra aplicación sin preocuparnos por el hardware.

Fuente – Diferencia de Deployment entre Módulos

 

Diseño Tolerante a Fallas

Como los servicios pueden fallar en cualquier momento, las aplicaciones deben ser diseñadas para tolerar estos fallos. Por esto, es importante hacer énfasis en el monitoreo y logging en tiempo real de la aplicación, ya sea con un dashboard para visualizar el estado de cada servicio, así como con métricas relevantes para determinar si el servicio está funcionando como es debido.

Diseño evolutivo

En el mundo de los microservicios, es preferible solo usar versionado como último recurso. Para esto, necesitamos diseñar las aplicaciones tan tolerables como sea posible, a cambios de sus suppliers. Los servicios deben ser capaces de evolucionar y escalar independientemente, sin tener que replicar cambios en el otro. Es importante considerar que un servicio puede cambiar constantemente, ser reescrito, o inclusive eliminarse. Este cambio no debe afectar a otros servicios y a la integración del sistema a lo largo de su ciclo de vida.

Pros vs Cons

Como menciona en su artículo mi compañero Rodolfo Cordero, los microservicios ofrecen una serie de ventajas en escalabilidad, flexibilidad para usar distintas tecnologías y tener un mejor manejo de versiones. Además, nos ofrecen realizar Deploys parciales y separación de responsabilidades.  De igual manera, Rodolfo nos explica cómo los microservicios nos pueden causar varios inconvenientes, dependiendo de la experiencia del equipo encargado de mantener la infraestructura del sistema. Adicionalmente, nuestro microservicio puede convertirse en un nanoservicio, siendo su costo operacional (comunicaciones, configuración, debugging) un factor que sobrepase su utilidad.

¿Son los microservicios el futuro?

Uno nunca se puede imaginar cuándo su aplicación puede pasar, de ser un simple inventario para las ventas de libros desde el garaje de tu casa, a ser el sistema que sostiene el retailer en línea más grande del mundo (Amazon). No está de más prepararnos para que nuestra aplicación evolucione y, diseñarla para soportar todo lo que implica tener un sistema con múltiples funcionalidades, donde cada una pueda crecer por sí misma y cada componente sea un producto individual.

Esto no quiere decir que las aplicaciones monolíticas serán deprecadas. Son dos arquitecturas que pueden convivir una con otra, inclusive dentro de la misma aplicación. Actualmente es un reto en las grandes empresas cambiar los esquemas, diseños y arquitecturas que ya forman parte del stack tecnológico y de la marca legacy de la empresa. Dependiendo de las necesidades y capacidades del negocio, podemos identificar si nuestra aplicación va a necesitar ser dividida en varios servicios y, si estos pueden convivir de tal manera que no se vea afectada la integridad del sistema en general.

En la siguiente entrega de esta serie de artículos sobre los microservicios, daremos una introducción a su implementación a través de ASP.NET Core y, hablaremos de las tecnologías que podemos utilizar para tener un ambiente capaz de soportar el desarrollo de aplicaciones bajo esta arquitectura.

Alberto Rojas

Alberto Rojas es desarrollador .NET en intive-FDV desde mayo de 2018. Ingeniero en Informática graduado de la Universidad Católica Andrés Bello de Caracas, su curiosidad lo lleva constantemente a asistir a cursos de diferentes áreas de la tecnología (frontend, mobile, videojuegos, pixel art), de otros idiomas y de temas de actualidad (cryptocurrency, startups). Gamer y amante de la literatura, disfruta mucho de recorrer la ciudad en rollers.

Deja un comentario