¿Qué es un microservicio en términos prácticos?
Un microservicio es una aplicación pequeña y autónoma que implementa una capacidad de negocio completa y bien delimitada. En la práctica, “micro” no significa “pocas líneas de código”, sino: (1) un límite claro del servicio, (2) una responsabilidad única, y (3) comunicación explícita con otros servicios a través de contratos (normalmente HTTP/REST o mensajería).
Límites del servicio (service boundary)
El límite define qué datos y reglas pertenecen al servicio y cuáles no. Todo lo que esté dentro del límite puede cambiarse sin coordinar con otros equipos, siempre que se mantenga el contrato externo. Una regla práctica: si para implementar una funcionalidad necesitas tocar la base de datos de otro servicio, el límite está mal definido.
Responsabilidad única (single responsibility)
Un microservicio debe tener un “por qué” de cambio principal. Si el servicio cambia por razones distintas (por ejemplo, reglas de precios y reglas de envío), probablemente estás mezclando responsabilidades.
Comunicación entre servicios
Los microservicios colaboran mediante APIs o eventos. La comunicación debe ser explícita, versionable y observable. En términos prácticos: un servicio A no “importa” clases de B; A consume un endpoint de B o reacciona a un evento publicado por B.
- Síncrona (HTTP): útil para consultas y comandos simples, con cuidado de latencia y disponibilidad.
- Asíncrona (mensajería/eventos): útil para desacoplar, tolerar fallos y escalar flujos.
Criterios para decidir la granularidad
La granularidad es el tamaño “correcto” del servicio. No hay un número mágico; se decide con criterios de dominio y de diseño. Tres criterios prácticos: bounded context, cohesión y acoplamiento.
- Escuche el audio con la pantalla apagada.
- Obtenga un certificado al finalizar.
- ¡Más de 5000 cursos para que explores!
Descargar la aplicación
1) Bounded Context (contexto delimitado)
Un bounded context es un área del dominio donde los términos y reglas tienen un significado consistente. Si una misma palabra cambia de significado según el área (por ejemplo, “cliente” en marketing vs. “cliente” en facturación), eso sugiere contextos distintos y, potencialmente, servicios distintos.
2) Cohesión
Un servicio debe agrupar funcionalidades que “van juntas” y evolucionan juntas. Señales de alta cohesión: las mismas reglas de negocio se aplican a la mayoría de casos del servicio, y los cambios suelen afectar a componentes internos del mismo servicio, no a otros.
3) Acoplamiento
El acoplamiento mide cuánto depende un servicio de otros para funcionar. Un diseño sano minimiza dependencias en tiempo de ejecución y en tiempo de desarrollo. Señales de acoplamiento excesivo: llamadas en cadena (A→B→C), necesidad de transacciones distribuidas, o cambios frecuentes coordinados entre repositorios.
Reglas rápidas para ajustar el tamaño
- Si el servicio requiere despliegues coordinados con otro para cambios comunes, probablemente están demasiado acoplados.
- Si el servicio contiene múltiples subdominios con reglas distintas, probablemente está demasiado grande.
- Si el servicio es tan pequeño que casi todo lo hace llamando a otros, probablemente está demasiado fragmentado.
Cómo se traduce esto en proyectos Spring Boot independientes
En Spring Boot, un microservicio se materializa como un proyecto independiente con su propio ciclo de vida: repositorio (o módulo separado), configuración, pipeline de CI/CD, artefacto de despliegue y, típicamente, su propia base de datos (o al menos su propio esquema con control total).
Checklist práctico (paso a paso) para definir un servicio
- Escribe la capacidad de negocio en una frase: “Gestionar el catálogo de productos”, “Gestionar pedidos”, etc.
- Define el límite: lista qué entidades y reglas pertenecen al servicio y qué queda fuera.
- Define el contrato externo: endpoints o eventos que expone; y dependencias externas que consume.
- Define su modelo de datos: tablas/documentos que controla. Regla: nadie más escribe en tu almacenamiento.
- Define escenarios de interacción: qué llamadas hace a otros servicios y qué datos necesita realmente.
- Decide consistencia: qué operaciones requieren consistencia inmediata y cuáles pueden ser eventual.
- Crea el proyecto Spring Boot: un
build.gradle/pom.xmlpropio, unapplication.ymlpropio, y paquetes internos por capas.
Mapa de componentes típico dentro de un microservicio
Un microservicio Spring Boot suele organizarse en componentes internos que separan responsabilidades. Un mapa típico:
| Componente | Responsabilidad | Ejemplos |
|---|---|---|
| API (capa de entrada) | Exponer contratos (REST), validar entrada, mapear DTOs | @RestController, DTOs, validaciones |
| Lógica de dominio / aplicación | Casos de uso, reglas, orquestación | Servicios de aplicación, comandos, políticas |
| Persistencia (capa de salida) | Acceso a datos y mapeo a entidades persistentes | Repositorios, adaptadores, mappers |
| Integraciones | Clientes HTTP, mensajería, adaptadores externos | Clients, publishers/subscribers |
Ejemplo de estructura de paquetes (orientativa)
com.ejemplo.catalogo ├─ api │ ├─ ProductController.java │ ├─ dto │ └─ mapper ├─ application │ ├─ CreateProductUseCase.java │ ├─ UpdateStockUseCase.java │ └─ service ├─ domain │ ├─ model │ ├─ policy │ └─ exception ├─ infrastructure │ ├─ persistence │ │ ├─ JpaProductRepository.java │ │ └─ entity │ └─ integration │ ├─ OrdersClient.java │ └─ events └─ CatalogoApplication.javaLa idea clave: el dominio y la aplicación no dependen de detalles de infraestructura; la infraestructura “se conecta” hacia dentro mediante interfaces.
Reglas de diseño para evitar dependencias cruzadas
1) No compartir base de datos entre servicios
Cada servicio controla su persistencia. Si otro servicio necesita datos, los obtiene por API/eventos. Esto evita acoplamiento por esquema y cambios coordinados.
2) No compartir modelos internos (clases) entre servicios
Evita librerías compartidas con entidades JPA o DTOs “comunes” que terminan forzando cambios sincronizados. Si necesitas reutilizar, reutiliza estándares (OpenAPI/JSON Schema) o librerías pequeñas y estables (por ejemplo, utilidades técnicas), no el modelo de negocio.
3) Contratos explícitos y versionables
Define contratos de API como “producto” del servicio. Mantén compatibilidad hacia atrás cuando sea posible. Si cambias un campo, considera versionar o hacer el cambio aditivo.
4) Dependencias unidireccionales dentro del servicio
Evita que la capa de dominio dependa de la capa de API o persistencia. Una regla simple: api puede depender de application; application puede depender de domain; infrastructure depende de application/domain, pero no al revés.
5) Evitar orquestación excesiva entre servicios
Si un flujo requiere múltiples llamadas síncronas encadenadas, considera eventos o mover reglas al servicio que “posee” la decisión. La coordinación debe minimizarse para reducir fallos en cascada.
Mini caso: dividir un dominio simple en Catálogo y Pedidos
Dominio: una tienda en línea básica con productos y pedidos. Objetivo: separar en dos microservicios con límites claros y justificar la partición.
1) Identificar capacidades y bounded contexts
- Catálogo: gestión de productos (alta/edición), descripción, precio de lista, disponibilidad publicada, categorías.
- Pedidos: creación de pedidos, líneas de pedido, estado (CREADO, PAGADO, ENVIADO), cálculo de totales del pedido, historial.
Justificación: “producto” y “pedido” evolucionan por razones distintas. Catálogo cambia por marketing/merchandising; pedidos cambia por logística/pagos/operaciones.
2) Definir propiedad de datos
- Catálogo es dueño de
Product(id, nombre, precio, atributos, stock o disponibilidad según el diseño). - Pedidos es dueño de
OrderyOrderLine.
Regla aplicada: Pedidos no escribe en tablas de Catálogo, y Catálogo no escribe en tablas de Pedidos.
3) Definir interacción entre servicios
Escenario: crear un pedido requiere conocer productos y precios.
- Opción A (síncrona): Pedidos consulta a Catálogo para validar productos y obtener precio actual al momento de compra.
- Opción B (asíncrona/eventos): Catálogo publica eventos de cambios de producto (precio, nombre, disponibilidad) y Pedidos mantiene una “vista” local para validar sin llamadas en tiempo real.
Para un primer corte simple, la opción A suele ser suficiente; si la latencia o disponibilidad se vuelve crítica, la opción B reduce acoplamiento en tiempo de ejecución.
4) Traducir a proyectos Spring Boot
- catalog-service: proyecto Spring Boot independiente con su API de productos y su persistencia.
- order-service: proyecto Spring Boot independiente con su API de pedidos y su persistencia.
5) Contratos mínimos (ejemplo)
Catálogo expone:
GET /products/{id}→ datos públicos del producto (nombre, precio, estado)GET /products?ids=...→ consulta por lote para líneas de pedido
Pedidos expone:
POST /orders→ crear pedido con líneas (productId, quantity)GET /orders/{id}→ consultar estado y detalle
6) Justificación final de la partición
- Cohesión: Catálogo agrupa reglas de producto; Pedidos agrupa reglas de ciclo de vida del pedido.
- Acoplamiento: la dependencia se limita a un contrato (consulta de producto o eventos), evitando compartir base de datos o modelos internos.
- Escalabilidad organizacional: equipos pueden evolucionar cada servicio con despliegues independientes.