En esta lección vamos a ver la organización de proyectos de microservicios. Saber cómo escribir código es solo una parte del trabajo. Si los microservicios están mal organizados, la aplicación se convertirá en un sistema confuso e ingobernable — como una serie donde las tramas se contradicen entre sí y los personajes actúan de forma ilógica. Así que vamos a ver cómo estructurar correctamente los proyectos para una arquitectura de microservicios.
Imagina que estás construyendo un edificio de varios pisos, donde cada habitación la ocupa un microservicio. Todo está bien hasta que decides que la cocina debe ir en la azotea y el baño en el sótano. Sí, nadie prohíbe hacerlo, pero está claro que es incómodo.
Problemas similares ocurren en programación. Si tus microservicios están mal estructurados:
- Los proyectos se vuelven difíciles de mantener. Los desarrolladores se confunden sobre qué servicio es responsable de qué.
- El despliegue se vuelve una pesadilla. Cualquier cambio puede requerir recompilar una enorme cantidad de código o reconfigurar toda la aplicación.
- Los equipos no pueden trabajar eficazmente. La autonomía de los servicios se pierde cuando un microservicio depende de un montón de otros.
Así que una buena arquitectura no es solo estética, es una necesidad.
Principios de la descomposición de microservicios
1. Separación de responsabilidades (Separation of Concerns)
Cada microservicio debe ser responsable solo de un área funcional. Es la ideología "haz una cosa y hazla bien". Por ejemplo:
- Servicio de usuarios (
User Service) — responsable del registro, la autorización y el almacenamiento de perfiles. - Servicio de pedidos (
Order Service) — gestiona el proceso de creación y procesamiento de pedidos. - Servicio de pagos (
Payment Service) — procesa pagos y gestiona transacciones.
¿Te preguntas cómo decidir "dónde detenerse"? Aquí ayuda el enfoque de "domain-driven design" (Domain-Driven Design, DDD), que indica cómo identificar las grandes áreas funcionales de tu aplicación.
2. Independencia de los servicios
Los microservicios deben ser lo más independientes posible. Esto significa:
- Cada servicio posee sus propios datos. Nunca, te digo, NUNCA te conectes directamente a la base de datos de otro servicio.
- Minimiza las llamadas entre servicios. Si tu servicio "depende" de otros, un fallo en un sitio puede arrastrar a todo el sistema.
3. Aislamiento por dominios de negocio
Debes dividir los servicios según los problemas de negocio que resuelven. Por ejemplo:
- Si haces una tienda online, puedes separar servicios para usuarios, productos, pedidos y pagos.
- Si desarrollas un sistema CRM, separa servicios para la gestión de clientes, oportunidades y campañas de marketing.
Estructura de un proyecto de microservicios
Ahora veamos cómo estructurar la base de código. Aquí tienes un ejemplo de estructura:
ecommerce/ # Carpeta raíz del proyecto
├── user-service/ # Microservicio de usuarios
│ ├── src/ # Código fuente
│ │ ├── main/
│ │ │ ├── java/com/example/user/ # Paquetes
│ │ │ │ ├── controller/
│ │ │ │ ├── service/
│ │ │ │ ├── repository/
│ │ │ │ ├── model/
│ │ │ └── resources/ # Archivos de configuración
│ │ └── test/
│ └── Dockerfile # Instrucción para el contenedor
├── order-service/ # Microservicio de pedidos
│ ├── src/
│ └── Dockerfile
├── payment-service/ # Microservicio de pagos
│ ├── src/
│ └── Dockerfile
└── config/ # Configuraciones centralizadas
├── docker-compose.yml # Configuración para el arranque
└── eureka-config.yml # Configuración de Service Discovery
Una buena estructura de paquetes dentro de cada microservicio permite encontrar el código fácilmente:
controller/— aquí van todos los controladores (por ejemplo, REST API).service/— aquí está la lógica de negocio.repository/— acceso a la base de datos.model/— descripción de entidades, por ejemplo,User,Order.
Práctica: separamos la aplicación en microservicios
Supongamos que desarrollamos una tienda online. Tenemos tres áreas principales:
- Usuarios: registro y autenticación.
- Productos: gestión del catálogo de artículos.
- Pedidos: creación de pedidos y gestión de los mismos.
Crearemos tres microservicios: UserService, ProductService, OrderService.
- Primero creamos un proyecto nuevo con Spring Initializr (
user-service):- Incluimos las dependencias: Spring Web, Spring Data JPA, Spring Boot DevTools, H2 Database.
- Estructuramos los paquetes:
com.example.user ├── controller/ ├── service/ ├── repository/ ├── model/ - Creamos una entidad sencilla:
@Entity public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String email; // Getters y setters } - Añadimos el controlador:
@RestController @RequestMapping("/users") public class UserController { @GetMapping public String getAllUsers() { return "¡Lista de usuarios!"; } }
Creación de ProductService y OrderService
El proceso es similar, pero usamos nuestros modelos de dominio (Product, Order) para cada servicio.
Cómo gestionar las dependencias entre servicios
A veces los servicios deben interactuar entre sí. Por ejemplo, el servicio de pedidos (OrderService) puede consultar al servicio de productos (ProductService), para comprobar la disponibilidad de un artículo.
Enfoques:
- REST API. Un servicio hace una petición a otro a través de HTTP.
- Intercambio de datos asíncrono. Usa brokers de mensajes como Kafka si quieres romper el acoplamiento directo entre servicios.
Consejos útiles y errores típicos
- No intentes diseñar la arquitectura perfecta a la primera. Dividir el sistema en microservicios puede ser un proceso iterativo.
- No concentres demasiada lógica en un solo microservicio. Si el código empieza a crecer y se vuelve complejo, es señal de que hay que extraer un nuevo servicio.
- Prueba los microservicios por separado. Asegúrate de que cada servicio funciona de forma independiente.
Acabamos de empezar a analizar la arquitectura de microservicios. Es importante recordar que no son un fin en sí mismos, sino una herramienta útil para resolver problemas de negocio.
GO TO FULL VERSION