En el mundo del desarrollo de software, los microservicios son un enfoque de arquitectura en el que una aplicación o un sistema se divide en componentes pequeños e independientes. Cada una de estas partes, o microservicios, cumple una función específica dentro de un sistema y funcionan como una unidad autónoma y auto-contenida.
A continuación vas encontrar información útil sobre
Para profundizar más sobre el tema también puedes consultar nuestra Pragma Talk, una conferencia en la que hacemos una introducción detallada a la arquitectura de mircroservicios.
Y si lo que buscas es trabajar en una multinacional con grandes proyectos y en compañía de una comunidad de profesionales que te ayudan a crecer, consulta nuestra oferta de empleos y lleva tu carrera al siguiente nivel. Ahora sí, hablemos de las ventajas de usar la arquitectura de microservicios.
La arquitectura de microservicios surgió para superar algunas de las limitaciones más comunes de las arquitecturas monolíticas y las arquitecturas orientadas a servicio (SOA). Entre sus principales beneficios encontramos:
Las arquitecturas de microservicios por lo general van de la mano con un enfoque de diseño de software conocido como Domain Driven Disign o DDD. A continuación encontrarás algunos de los conceptos clave de este enfoque que te pueden ayudar a identificar un microservicio.
Propuesto por Eric Evans, el DDD consiste en darle prioridad a los conceptos, términos y procesos del negocio (dominio), por encima de la estructura técnica o los requisitos funcionales.
Cuando se usa DDD en conjunto con la arquitectura de microservicios, el resultado son activos digitales que están compuestos por servicios autónomos e independientes, que están especializados en cada área del dominio empresarial.
La experiencia es fundamental para identificar dónde están los límites entre uno y otro microservicio, sin embargo, DDD también cuenta con 4 conceptos fundamentales que nos pueden ayudar en esta tarea:
Representan conceptos del dominio del negocio que, por sus atributos y su comportamiento, tienen una identidad única y distinguible.
Para entenderlo mejor podemos tomar el ejemplo del objeto “Cliente” en un e-commerce.
En este caso, un cliente es una entidad con un ID único que, al mismo tiempo, tiene diferentes atributos como nombre, dirección, correo electrónico, número de teléfono, etc.
public class Cliente { private String id; private String nombre; private String email; private List<Pedido> historialPedidos; public Cliente(String id, String nombre, String email) { this.id = id; this.nombre = nombre; this.email = email; this.historialPedidos = new ArrayList<>(); } // Getters y setters public void agregarPedido(Pedido pedido) { historialPedidos.add(pedido); } public void eliminarPedido(Pedido pedido) { historialPedidos.remove(pedido); } } |
Los value objects también representan conceptos del dominio pero NO tienen una identidad distinguible. Están definidos por atributos pero a diferencia de las entidades, los value objects pueden igualarse a otros si el valor de esos atributos es el mismo. Veámos un ejemplo.
Es común en muchas aplicaciones la fecha de nacimiento sea considerada un concepto que requiere tratarse como un todo pero no necesita una identidad única en el dominio.
En este caso, “FechaNacimiento” va a estar compuesto por los atributos de “dia”, “mes” y “anio”.
public class FechaNacimiento { |
También conocidos como agregados, agrupan un conjunto de entidades y objetos de valor valor en una unidad coherente.
Un agregado va a estar definido por una raíz (aggregate root), que es una entidad que tiene la responsabilidad principal de mantener la coherencia y la consistencia del conjunto de objetos que forman parte del agregado.
Solo se puede acceder y modificar el agregado a través de su raíz, lo que ayuda a preservar la integridad transaccional del conjunto de objetos y facilita la gestión del modelo de dominio.
Podemos ver un ejemplo de todo esto en un dominio que gestiona pedidos en línea. En estos casos, tendríamos un agregado que contiene atributos como id y cliente y una lista de “items” que representan los productos solicitados en el pedido.
El agregado “Pedido” debe tener métodos que permitan operaciones como agregar o eliminar un”ItemPedido”. También puede tener otros métodos y lógica relacionados con la gestión del pedido, como aplicar descuentos, calcular el total del pedido, establecer direcciones de envío, etc.
Por otro lado, el agregado “Pedido” debe realizar validaciones y aplicar reglas de negocio específicas para garantizar que el pedido esté en un estado válido y coherente.
public class Pedido { |
Delimitar contextos nos permite dividir un sistema en partes pequeñas y manejables.
En cada contexto hay un conjunto de conceptos y reglas de negocio por lo que, si queremos facilitar procesos de integración y mantener la consistencia del sistema es fundamental tener contextos bien delimitados que además se puedan comunicar entre sí.
En un sistema de comercio podríamos tener un contexto de “Ventas” y otro contexto de “Inventario”.
En “Ventas”,el enfoque es gestionar y procesar pedidos de clientes, realizar pagos, generar facturas y gestionar el ciclo de vida de los pedidos. Este contexto tendría entidades como “Cliente”, “Pedido”, “Producto” y “Factura” y el lenguaje de programación que empleemos será el que mejor se adapte a esos conceptos así como a reglas de negocio relacionadas con las ventas.
Por otro lado, en el contexto “Inventario” el enfoque va a ser administrar y controlar el stock de productos, realizar seguimiento a la disponibilidad y gestionar el reabastecimiento. Al igual que con el ejemplo anterior, en este contexto vamos a tener un lengua que se adapte mejor a este contexto y entidades específicas que en este caso podrían ser "Producto", "Stock", "Proveedor" y "Orden de compra".
Si bien los microservicios son una buena estrategia para desarrollar sistemas grandes, esto conlleva distintos retos que tendrán que ser sorteados de diferentes maneras. Algunos de estos retos son los siguientes:
Cuando hablamos de sistemas, la resiliencia es la capacidad para resistir y recuperarse de fallos. Para alcanzarla, es necesario implementar estrategias y mecanismos que nos permitan manejar situaciones de fallo, como la tolerancia a fallos y la capacidad de respuesta ante condiciones adversas.
Entre los patrones más utilizados para mejorar la resiliencia y la estabilidad de las aplicaciones.
Actualmente una de las librerías más usadas es Resilience4J (consulta aquí la documentación oficial).
Dado que estamos trabajando con distintos microservicios, donde cada uno es dueño de su propia información y base de datos, a menudo nos encontramos en la necesidad de lograr que nuestros microservicios se comuniquen entre ellos.
Sin embargo, si en algún punto esta comunicación falla, ¿cómo podemos detectar si algo salió mal y revertir los cambios en los microservicios que no fallaron? Para este tipo de situaciones utilizamos el siguiente patrón:
Se utiliza para garantizar la consistencia en operaciones que involucran múltiples pasos y servicios.
En lugar de utilizar transacciones globales, el patrón Saga divide la operación en pasos individuales y cada paso es representado por una "compensación" que puede deshacer las acciones realizadas en caso de fallo.
Este patrón puede tener dos enfoques diferentes:
Orquestación: En este enfoque los participantes son gestionados desde un único punto: el orquestador de la saga. Mediante una primera operación orquesta las llamadas secuenciales al conjunto de participantes para llevar a cabo la transacción de negocio distribuida.
Coreografía: Los participantes reaccionan de forma autónoma. Cada servicio participa en la transacción distribuida de forma individual. Siendo responsable de gestionar su propia transacción local según la operación resultante de otro participante: continuar la saga o ejecutar la transacción de compensación (deshaciendo cambios ya realizados) desencadenando los eventos de compensación.
Como decíamos al comienzo de este artículo, utilizar una arquitectura de microservicios es fundamental para crear activos digitales modulares capaces de evolucinar con las necesidades del negocio y de los usuarios finales.
Si quieres trabajar en un empresa donde podrás fortalecer tus habilidades en Java y arquitectura de microservicios, en compañía de una comunidad de expertos que te ayudan a llegar al siguiente nivel, explora nuestras vacantes: