S6 - Comunicación síncrona resiliente entre servicios
1. Introducción
Tiempo: 20 min.
1.1 Propósito
Implementar comunicación entre microservicios para resolver operaciones que requieren datos de otro servicio, manteniendo respuestas controladas ante errores.
1.2 Resultado de aprendizaje
El estudiante implementa una llamada interna entre microservicios, valida el flujo distribuido y evidencia una respuesta controlada ante fallos.
1.3 Producto de sesión
producto-ms consulta catalogo-ms para validar o enriquecer información de categorías, con trazabilidad y manejo básico de errores.
1.4 Motivacion de la sesión
En un sistema distribuido, ningun microservicio debe leer directamente la base de datos de otro. Si producto-ms necesita información de categorías, debe comunicarse con catalogo-ms por una API interna.
1.5 Ubicación en el curso
- Unidad: U2 - Sistema distribuido robusto.
- Producto de unidad: sistema distribuido seguro, resiliente, consistente, observable e integrado con cliente frontend.
- Avance del producto en esta sesión: comunicación síncrona entre servicios.
2. Explica
Tiempo: 15 min.
2.1 Conceptos clave
- Comunicación síncrona.
- Cliente HTTP interno.
- DTO entre servicios.
- Timeout y error controlado.
- Trazabilidad de peticiones entre microservicios.
2.2 Arquitectura del producto en ecom
2.2.1 Comunicación síncrona en DEV
flowchart LR
Cliente["Cliente<br/>PowerShell / bash"]
Gateway["Gateway<br/>localhost:18080"]
Eureka["Eureka<br/>localhost:18761"]
Producto["producto-ms<br/>puerto dinamico"]
Catalogo["catalogo-ms<br/>puerto dinamico"]
ProductoDB["producto_db"]
CatalogoDB["catálogo_db"]
Cliente --> Gateway
Gateway --> Producto
Gateway -. "descubre servicios<br/>localhost:18761/eureka" .-> Eureka
Producto -. "descubre catalogo-ms<br/>localhost:18761/eureka" .-> Eureka
Producto -->|"consulta categoría<br/>http://catalogo-ms"| Catalogo
Producto --> ProductoDB
Catalogo --> CatalogoDB
2.2.2 Comunicación síncrona en PROD local
flowchart LR
Cliente["Cliente<br/>PowerShell / bash"]
subgraph Docker["Docker Network: ecom-prod-net"]
Gateway["ecom-gateway<br/>8080 interno"]
Eureka["eureka<br/>8761 interno"]
Producto["producto-ms<br/>8080 interno"]
Catalogo["catalogo-ms<br/>8080 interno"]
end
Cliente -->|"GET localhost:28082/api/v1/productos"| Gateway
Gateway --> Producto
Gateway -. "descubre servicios<br/>http://eureka:8761/eureka" .-> Eureka
Producto -. "descubre catalogo-ms<br/>http://eureka:8761/eureka" .-> Eureka
Producto -->|"consulta categoría<br/>http://catalogo-ms:8080"| Catalogo
2.3 Observabilidad y diagnóstico
Revisar logs de producto-ms, logs de catalogo-ms, correlation id, health y respuesta HTTP cuando catalogo-ms no responde.
3. Aplica: actividad práctica guiada
Tiempo: 3h.
La ruta principal de la sesión es construir desde cero la comunicación entre producto-ms y catalogo-ms. Si el estudiante necesita avanzar más rápido, puede usar la ruta alternativa del paso 3.17.
3.1 Identificar servicios base
Producto del paso: catalogo-ms y producto-ms identificados como servicios que participaran en la comunicación.
En esta sesión:
catalogo-msexpone categorías.producto-msconsultacatalogo-mspara obtener el detalle de la categoría de un producto.- La llamada se hace por nombre lógico registrado en Eureka, no por puerto fijo.
3.2 Agregar dependencia de cliente HTTP interno
Producto del paso: producto-ms preparado para usar OpenFeign.
En services/producto-ms/pom.xml, agrega:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
Si también se trabajara respuesta controlada con Circuit Breaker, agrega:
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot3</artifactId>
</dependency>
En la clase principal de producto-ms, habilita Feign:
package com.upeu.producto;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients
public class ProductoApplication {
public static void main(String[] args) {
SpringApplication.run(ProductoApplication.class, args);
}
}
3.3 Crear DTO de categoría
Producto del paso: contrato de datos recibido desde catalogo-ms.
Crea:
services/producto-ms/src/main/java/com/upeu/producto/dto/CategoriaDto.java
Pega:
package com.upeu.producto.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CategoriaDto {
private Long id;
private String nombre;
private String descripcion;
}
3.4 Crear cliente interno hacia catalogo-ms
Producto del paso: cliente Feign que consulta catalogo-ms por nombre lógico.
Crea:
services/producto-ms/src/main/java/com/upeu/producto/client/CatalogoClient.java
Pega:
package com.upeu.producto.client;
import com.upeu.producto.dto.CategoriaDto;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(name = "catalogo-ms")
public interface CatalogoClient {
@GetMapping("/api/v1/categorias/{id}")
CategoriaDto findCategoriaById(@PathVariable("id") Long id);
}
3.5 Integrar cliente en el servicio de producto
Producto del paso: producto-ms devuelve detalle de producto enriquecido con categoría.
Inyecta CatalogoClient en el servicio de producto:
private final CatalogoClient catalogoClient;
Agrega un método de consulta de detalle:
@Override
@Transactional(readOnly = true)
@CircuitBreaker(name = "catalogo", fallbackMethod = "fallbackCategoria")
public ProductoResponse findDetalleById(Integer id) {
Producto producto = getProductoById(id);
CategoriaDto categoria = catalogoClient.findCategoriaById(
producto.getIdCategoria().longValue());
return ProductoResponse.builder()
.id(producto.getId())
.nombre(producto.getNombre())
.descripcion(producto.getDescripcion())
.idCategoria(producto.getIdCategoria())
.categoria(categoria)
.build();
}
3.6 Configurar timeout o respuesta controlada
Producto del paso: respuesta controlada si catalogo-ms no responde.
Agrega el fallback en el mismo servicio:
public ProductoResponse fallbackCategoria(Integer id, Throwable ex) {
Producto producto = getProductoById(id);
return ProductoResponse.builder()
.id(producto.getId())
.nombre(producto.getNombre())
.descripcion(producto.getDescripcion())
.idCategoria(producto.getIdCategoria())
.categoria(null)
.build();
}
En el controlador de productos, expone el endpoint de detalle si no existe:
@GetMapping("/detalle/{id}")
public ProductoResponse findDetalleById(@PathVariable Integer id) {
return productoService.findDetalleById(id);
}
3.7 Levantar infraestructura en DEV
PowerShell / bash macOS/Linux:
cd infra/config
mvn spring-boot:run
En otra terminal:
cd infra/eureka
mvn spring-boot:run
En otra terminal:
cd infra/gateway
mvn spring-boot:run
3.8 Levantar catalogo-ms en DEV
PowerShell / bash macOS/Linux:
cd services/catalogo-ms
docker compose -f compose-dev.yml up -d
mvn spring-boot:run
3.9 Levantar producto-ms en DEV
PowerShell / bash macOS/Linux:
cd services/producto-ms
docker compose -f compose-dev.yml up -d
mvn spring-boot:run
3.10 Probar flujo correcto
PowerShell:
Invoke-RestMethod -Method Get -Uri "http://localhost:18080/api/v1/productos"
bash macOS/Linux:
curl http://localhost:18080/api/v1/productos
3.11 Probar detalle o validación de categoría
Ejecutar una operación de producto que obligue a consultar catalogo-ms.
3.12 Probar error controlado
Detener catalogo-ms o simular una categoría inexistente y verificar que producto-ms responde de forma controlada.
3.13 Validar trazabilidad en logs
Revisa logs de producto-ms y catalogo-ms para confirmar la llamada interna y el correlation id.
3.14 Preparar PROD local
Primero levantar infraestructura y luego microservicios:
infra -> config + eureka + gateway
services/catalogo-ms
services/producto-ms
3.15 Probar comunicación en PROD local
PowerShell / bash macOS/Linux:
cd infra
docker compose up -d --build config eureka gateway
En otra terminal:
cd services/catalogo-ms
docker compose up -d --build
En otra terminal:
cd services/producto-ms
docker compose up -d --build
Prueba por Gateway PROD con PowerShell:
Invoke-RestMethod -Method Get -Uri "http://localhost:28082/api/v1/productos"
Prueba por Gateway PROD con bash macOS/Linux:
curl http://localhost:28082/api/v1/productos
3.16 Validar evidencias de cierre de la práctica
Verifica:
producto-msconsultacatalogo-ms.- La llamada ocurre por nombre lógico.
- El flujo correcto responde.
- El error controlado responde sin romper el sistema.
- PROD local mantiene el mismo comportamiento.
3.17 Ruta alternativa: clonar y ejecutar a partir del tag final de la sesión
git clone --branch vs06-comunicacion-sincronica https://github.com/261dist/ecom.git ecom-s06
cd ecom-s06
4. Crea: actividad autónoma
Tiempo: 4h fuera del aula.
Esta actividad autónoma se desarrolla sobre el proyecto de fin de curso del equipo. El producto de la unidad se construye por acumulacion de los avances de cada sesión; por eso, la evidencia de esta sesión debe incorporarse a la documentación del proyecto y quedar trazable en GitHub.
4.1 Plantilla de evidencia individual
Entrega un PDF:
El PDF de esta sesión debe generarse como impresion o exportacion de la sección correspondiente en MkDocs o una herramienta equivalente. No se acepta un PDF armado manualmente fuera de la documentación del proyecto.
S06_Equipo##_ApellidoNombre.pdf
4.1.1 Datos del estudiante
- Nombre:
- Equipo:
- Sesión: S06 - Comunicación síncrona resiliente entre servicios
- Rol o aporte realizado:
- Link de GitHub:
4.1.2 Trabajo autónomo realizado
- Evidenciar llamada de
producto-msacatalogo-ms. - Probar caso exitoso.
- Probar error controlado.
- Explicar por qué no se comparte base de datos.
- Registrar aporte individual.
4.2 Criterios mínimos de aceptación
- PDF con nombre correcto.
- Evidencia de comunicación entre servicios.
- Evidencia de caso correcto y error controlado.
- Aporte individual verificable.
5. Cierre evaluativo
Tiempo: 20 min.
5.1 Resultados esperados
producto-msconsumecatalogo-ms.- El flujo distribuido funciona.
- Los errores internos se responden de forma controlada.
5.2 Evidencia del producto de sesión
Entrega individual:
S06_Equipo##_ApellidoNombre.pdf
5.3 Preguntas de defensa y reflexión
- Por qué un microservicio no debe leer la BD de otro?
- Qué pasa si el servicio llamado no responde?
- Qué evidencia demuestra la comunicación entre servicios?
- Cómo ayuda el correlation id?
5.4 Rúbrica de evaluación
| Dimensión | Peso | 3 - Logro destacado | 2 - Logro | 1 - Proceso | 0 - Inicio | Puntuación obtenida |
|---|---|---|---|---|---|---|
| 1. Comunicación entre servicios | 2 | Evidencia flujo completo y consistente entre servicios. | Evidencia llamada funcional. | Evidencia parcial o poco clara. | No evidencia comunicación. | |
| 2. Contrato y datos | 2 | Usa DTOs y valida datos correctamente. | Usa contrato funcional. | Contrato parcial o confuso. | No evidencia contrato. | |
| 3. Manejo de errores | 2 | Evidencia error controlado y explica causa. | Evidencia respuesta ante error. | Error probado parcialmente. | No evidencia manejo de error. | |
| 4. Observabilidad | 2 | Evidencia logs/correlation id del flujo. | Evidencia logs suficientes. | Evidencia limitada. | No evidencia diagnóstico. | |
| 5. Aporte individual | 1 | Aporte claro y verificable. | Aporte identificable. | Aporte general. | No se identifica aporte. | |
| 6. Orden y reflexión | 1 | PDF ordenado y reflexión técnica clara. | Evidencia suficiente. | Evidencia poco clara. | PDF insuficiente. |
Puntuación acumulada = suma de (Peso * Puntuacion obtenida) = ____.
Nota final = (Puntuacion acumulada / 30) * 20 = ____.
Para usar la rúbrica con IA, solicita:
Evalúa el PDF usando la rúbrica de la sesión.
Para cada dimensión selecciona la puntuación obtenida usando la escala Inicio=0, Proceso=1, Logro=2, Logro destacado=3.
Justifica brevemente cada puntuación.
Calcula la puntuación acumulada con la fórmula: suma de (Peso * Puntuación obtenida).
Calcula la nota final sobre 20 con la fórmula: (Puntuación acumulada / 30) * 20.
Indica 2 fortalezas y 2 recomendaciones.