Quiz: Spring Cloud y Microservicios
Ponga a prueba sus conocimientos sobre arquitectura de microservicios y Spring Cloud.
30 preguntas - Haga clic en cada pregunta para revelar la respuesta.
Preguntas 1-10: Arquitectura de Microservicios
Pregunta 1: ¿Cuál es la diferencia entre monolito y microservicios?
Respuesta:
| Monolito | Microservicios |
|---|---|
| Una sola aplicación | Servicios independientes |
| Una base de datos | BD por servicio |
| Despliegue global | Despliegue independiente |
| Escalado global | Escalado por servicio |
| Simple al inicio | Complejo al inicio |
| Alto acoplamiento | Bajo acoplamiento |
Pregunta 2: ¿Cuándo elegir una arquitectura de microservicios?
Respuesta:
- Equipo grande (múltiples equipos)
- Necesidad de escalabilidad diferenciada
- Tecnologías diferentes por servicio
- Despliegues frecuentes e independientes
- Tolerancia a fallos por servicio
Evitar para: equipos pequeños, prototipos, aplicaciones simples.
Pregunta 3: ¿Qué es el Service Discovery?
Respuesta: Mecanismo que permite a los servicios encontrarse dinámicamente sin configuración estática de direcciones IP.
Service A: "¿Dónde está Service B?"
↓
Eureka Server: "Service B está en 192.168.1.10:8081 y 192.168.1.11:8081"
↓
Service A llama a Service B
Pregunta 4: ¿Qué es un API Gateway?
Respuesta: Punto de entrada único para todos los microservicios:
- Enrutamiento hacia los servicios
- Autenticación centralizada
- Rate limiting
- Balanceo de carga
- Logging/Monitoreo
Cliente → API Gateway → Service A
→ Service B
→ Service C
Pregunta 5: ¿Qué es un Circuit Breaker?
Respuesta: Patrón de resiliencia que "corta" las llamadas hacia un servicio defectuoso:
Estados:
CLOSED → Llamadas normales
OPEN → Llamadas bloqueadas (fallback)
HALF_OPEN → Prueba de recuperación
Evita cascadas de fallos.
Pregunta 6: ¿Qué es el patrón Saga?
Respuesta: Gestión de transacciones distribuidas mediante una secuencia de transacciones locales con compensaciones:
Order → Payment → Inventory → Shipping
↓ (fallo)
Compensación: reembolsar
Cada servicio gestiona su transacción y puede anular (compensar) si es necesario.
Pregunta 7: ¿Qué es CQRS?
Respuesta: Command Query Responsibility Segregation - separar las operaciones de lectura y escritura:
Comandos (Write) → Command Service → Write DB
Consultas (Read) → Query Service → Read DB (optimizada)
Permite optimizar cada lado de forma independiente.
Pregunta 8: ¿Qué es Event Sourcing?
Respuesta: Almacenar todos los eventos en lugar del estado actual:
Events:
1. UserCreated {id: 1, name: "John"}
2. UserEmailChanged {id: 1, email: "john@new.com"}
3. UserDeleted {id: 1}
Estado = replay de todos los eventos
Ventajas: auditoría completa, reconstrucción de estado, event replay.
Pregunta 9: ¿Cuáles son los 12 factores de una aplicación cloud-native?
Respuesta:
- Codebase: un repo, múltiples despliegues
- Dependencies: declaradas y aisladas
- Config: en el entorno
- Backing services: tratados como recursos adjuntos
- Build, release, run: etapas estrictamente separadas
- Processes: stateless
- Port binding: autocontenida
- Concurrency: escalado horizontal
- Disposability: arranque/parada rápidos
- Dev/prod parity: entornos similares
- Logs: flujo de eventos
- Admin processes: tareas puntuales
Pregunta 10: ¿Cómo gestionar la comunicación entre servicios?
Respuesta:
| Tipo | Protocolo | Uso |
|---|---|---|
| Sincrónico | REST/gRPC | Respuesta inmediata requerida |
| Asincrónico | RabbitMQ/Kafka | Desacoplamiento, eventos |
Preferir asincrónico cuando sea posible para la resiliencia.
Preguntas 11-20: Spring Cloud
Pregunta 11: ¿Cómo configurar Eureka Server?
Respuesta:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication { }
server:
port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
Pregunta 12: ¿Cómo registrar un servicio en Eureka?
Respuesta:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
spring:
application:
name: user-service
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
Pregunta 13: ¿Cómo llamar a otro servicio con RestTemplate y load balancing?
Respuesta:
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Service
public class OrderService {
private final RestTemplate restTemplate;
public User getUser(Long id) {
// Utiliza el nombre del servicio, no la URL
return restTemplate.getForObject(
"http://user-service/api/users/" + id, User.class);
}
}
Pregunta 14: ¿Cómo usar OpenFeign para llamadas entre servicios?
Respuesta:
@EnableFeignClients
@SpringBootApplication
public class OrderApplication { }
@FeignClient(name = "user-service")
public interface UserClient {
@GetMapping("/api/users/{id}")
User getUser(@PathVariable Long id);
}
@Service
public class OrderService {
private final UserClient userClient;
public Order createOrder(OrderRequest req) {
User user = userClient.getUser(req.getUserId());
// ...
}
}
Pregunta 15: ¿Cómo configurar Spring Cloud Config Server?
Respuesta:
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication { }
server:
port: 8888
spring:
cloud:
config:
server:
git:
uri: https://github.com/org/config-repo
default-label: main
Pregunta 16: ¿Cómo utiliza un servicio cliente el Config Server?
Respuesta:
# bootstrap.yml
spring:
application:
name: user-service
cloud:
config:
uri: http://localhost:8888
El servicio recupera user-service.yml desde el Config Server.
Pregunta 17: ¿Cómo configurar Spring Cloud Gateway?
Respuesta:
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/api/users/**
filters:
- StripPrefix=1
- id: order-service
uri: lb://order-service
predicates:
- Path=/api/orders/**
- Method=GET,POST
Pregunta 18: ¿Cómo agregar un filtro global en Gateway?
Respuesta:
@Component
public class LoggingFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("Request: {} {}",
exchange.getRequest().getMethod(),
exchange.getRequest().getPath());
return chain.filter(exchange).then(Mono.fromRunnable(() -> {
log.info("Response: {}",
exchange.getResponse().getStatusCode());
}));
}
@Override
public int getOrder() {
return -1;
}
}
Pregunta 19: ¿Cómo configurar Resilience4j Circuit Breaker?
Respuesta:
resilience4j:
circuitbreaker:
instances:
userService:
slidingWindowSize: 10
failureRateThreshold: 50
waitDurationInOpenState: 10000
permittedNumberOfCallsInHalfOpenState: 3
@CircuitBreaker(name = "userService", fallbackMethod = "fallback")
public User getUser(Long id) {
return userClient.getUser(id);
}
public User fallback(Long id, Exception ex) {
return new User(id, "Fallback User", "N/A");
}
Pregunta 20: ¿Cómo configurar el retry con Resilience4j?
Respuesta:
resilience4j:
retry:
instances:
userService:
maxAttempts: 3
waitDuration: 1000
enableExponentialBackoff: true
exponentialBackoffMultiplier: 2
@Retry(name = "userService")
@CircuitBreaker(name = "userService", fallbackMethod = "fallback")
public User getUser(Long id) {
return userClient.getUser(id);
}
Preguntas 21-30: Patrones Avanzados
Pregunta 21: ¿Cómo implementar un fallback con Feign?
Respuesta:
@FeignClient(name = "user-service", fallbackFactory = UserClientFallback.class)
public interface UserClient {
@GetMapping("/api/users/{id}")
User getUser(@PathVariable Long id);
}
@Component
public class UserClientFallback implements FallbackFactory<UserClient> {
@Override
public UserClient create(Throwable cause) {
return id -> new User(id, "Fallback", "N/A");
}
}
Pregunta 22: ¿Cómo implementar el rate limiting en Gateway?
Respuesta:
spring:
cloud:
gateway:
routes:
- id: api-route
uri: lb://api-service
predicates:
- Path=/api/**
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10
redis-rate-limiter.burstCapacity: 20
key-resolver: "#{@userKeyResolver}"
@Bean
public KeyResolver userKeyResolver() {
return exchange -> Mono.just(
exchange.getRequest().getRemoteAddress().getHostName()
);
}
Pregunta 23: ¿Cómo refrescar la configuración en caliente?
Respuesta:
@RefreshScope
@RestController
public class ConfigController {
@Value("${app.message}")
private String message;
@GetMapping("/message")
public String getMessage() {
return message;
}
}
# Disparar el refresh
curl -X POST http://localhost:8080/actuator/refresh
O con Spring Cloud Bus para propagar a todos los servicios.
Pregunta 24: ¿Cómo trazar las solicitudes distribuidas?
Respuesta: Con Micrometer Tracing (ex-Sleuth) + Zipkin:
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter-brave</artifactId>
</dependency>
management:
tracing:
sampling:
probability: 1.0
zipkin:
tracing:
endpoint: http://zipkin:9411/api/v2/spans
Cada solicitud tiene un traceId único propagado entre servicios.
Pregunta 25: ¿Cómo asegurar las comunicaciones entre servicios?
Respuesta:
- mTLS: certificados mutuos
- Propagación de JWT: token pasado entre servicios
- Service mesh: Istio, Linkerd
- Network policies: Kubernetes
// Propagación de JWT con Feign
@Configuration
public class FeignConfig {
@Bean
public RequestInterceptor authInterceptor() {
return template -> {
String token = SecurityContextHolder.getContext()
.getAuthentication().getCredentials().toString();
template.header("Authorization", "Bearer " + token);
};
}
}
Pregunta 26: ¿Cómo gestionar los secretos en microservicios?
Respuesta:
- Spring Cloud Config con encriptación
- Vault (HashiCorp)
- Kubernetes Secrets
- AWS Secrets Manager / Azure Key Vault
# Config Server con encriptación
spring:
cloud:
config:
server:
encrypt:
enabled: true
encrypt:
key: ${ENCRYPT_KEY}
Pregunta 27: ¿Cómo gestionar las versiones de API?
Respuesta:
- Versionado por URL:
/api/v1/users - Versionado por header:
Accept: application/vnd.api.v1+json - Query param:
/api/users?version=1
@RestController
@RequestMapping("/api/v1/users")
public class UserControllerV1 { }
@RestController
@RequestMapping("/api/v2/users")
public class UserControllerV2 { }
Pregunta 28: ¿Cómo desplegar microservicios con Kubernetes?
Respuesta:
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
spec:
replicas: 3
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: user-service:1.0
ports:
- containerPort: 8080
env:
- name: EUREKA_SERVER
value: "http://eureka:8761/eureka"
---
apiVersion: v1
kind: Service
metadata:
name: user-service
spec:
selector:
app: user-service
ports:
- port: 80
targetPort: 8080
Pregunta 29: ¿Cómo monitorear los microservicios?
Respuesta:
- Métricas: Prometheus + Grafana
- Logs: ELK Stack (Elasticsearch, Logstash, Kibana)
- Traces: Zipkin / Jaeger
- Alertas: Prometheus Alertmanager
Dashboard centralizado con:
- Latencia por servicio
- Tasa de error
- Throughput
- Dependencias
Pregunta 30: ¿Cuáles son las buenas prácticas de microservicios?
Respuesta:
- Bounded context: un servicio = un dominio de negocio
- Database per service: sin BD compartida
- API contracts: OpenAPI/Swagger
- Idempotencia: operaciones repetibles sin efecto
- Healthchecks: Actuator para cada servicio
- Circuit breakers: protección contra fallos
- Comunicación asíncrona: preferir cuando sea posible
- Logging centralizado: correlación por traceId
- Infrastructure as Code: Terraform, Helm
- Feature flags: despliegue progresivo
Puntuación
| Puntuación | Nivel |
|---|---|
| 27-30 | Excelente - Microservicios dominados |
| 21-26 | Bien - Algunas revisiones |
| 15-20 | Medio - Repase los capítulos |
| Menos de 15 | A revisar |