Quiz: Spring Cloud et Microservices
Testez vos connaissances sur l'architecture microservices et Spring Cloud.
30 questions - Cliquez sur chaque question pour révéler la réponse.
Questions 1-10: Architecture Microservices
Question 1: Quelle est la différence entre monolithe et microservices?
Réponse:
| Monolithe | Microservices |
|---|---|
| Une seule application | Services indépendants |
| Une base de données | DB par service |
| Déploiement global | Déploiement indépendant |
| Scaling global | Scaling par service |
| Simple au début | Complexe au début |
| Couplage fort | Couplage faible |
Question 2: Quand choisir une architecture microservices?
Réponse:
- Grande équipe (multiples équipes)
- Besoin de scalabilité différenciée
- Technologies différentes par service
- Déploiements fréquents indépendants
- Tolérance aux pannes par service
Éviter pour: petites équipes, prototypes, applications simples.
Question 3: Qu'est-ce que le Service Discovery?
Réponse: Mécanisme permettant aux services de se trouver dynamiquement sans configuration statique des adresses IP.
Service A: "Où est Service B?"
↓
Eureka Server: "Service B est à 192.168.1.10:8081 et 192.168.1.11:8081"
↓
Service A appelle Service B
Question 4: Qu'est-ce qu'un API Gateway?
Réponse: Point d'entrée unique pour tous les microservices:
- Routage vers les services
- Authentification centralisée
- Rate limiting
- Load balancing
- Logging/Monitoring
Client → API Gateway → Service A
→ Service B
→ Service C
Question 5: Qu'est-ce qu'un Circuit Breaker?
Réponse: Pattern de résilience qui "coupe" les appels vers un service défaillant:
États:
CLOSED → Appels normaux
OPEN → Appels bloqués (fallback)
HALF_OPEN → Test de récupération
Empêche les cascades de pannes.
Question 6: Qu'est-ce que le pattern Saga?
Réponse: Gestion des transactions distribuées via une séquence de transactions locales avec compensations:
Order → Payment → Inventory → Shipping
↓ (échec)
Compensation: rembourser
Chaque service gère sa transaction et peut annuler (compenser) si nécessaire.
Question 7: Qu'est-ce que CQRS?
Réponse: Command Query Responsibility Segregation - séparer les opérations de lecture et d'écriture:
Commandes (Write) → Command Service → Write DB
Requêtes (Read) → Query Service → Read DB (optimisée)
Permet d'optimiser chaque côté indépendamment.
Question 8: Qu'est-ce que l'Event Sourcing?
Réponse: Stocker tous les événements plutôt que l'état actuel:
Events:
1. UserCreated {id: 1, name: "John"}
2. UserEmailChanged {id: 1, email: "john@new.com"}
3. UserDeleted {id: 1}
État = replay de tous les événements
Avantages: audit complet, reconstruction d'état, event replay.
Question 9: Quels sont les 12 facteurs d'une application cloud-native?
Réponse:
- Codebase: un repo, plusieurs déploiements
- Dependencies: déclarées et isolées
- Config: dans l'environnement
- Backing services: traités comme ressources attachées
- Build, release, run: étapes strictement séparées
- Processes: stateless
- Port binding: auto-contenu
- Concurrency: scale horizontal
- Disposability: démarrage/arrêt rapides
- Dev/prod parity: environnements similaires
- Logs: flux d'événements
- Admin processes: tâches ponctuelles
Question 10: Comment gérer la communication inter-services?
Réponse:
| Type | Protocole | Usage |
|---|---|---|
| Synchrone | REST/gRPC | Réponse immédiate requise |
| Asynchrone | RabbitMQ/Kafka | Découplage, events |
Préférer asynchrone quand possible pour la résilience.
Questions 11-20: Spring Cloud
Question 11: Comment configurer Eureka Server?
Réponse:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication { }
server:
port: 8761
eureka:
client:
register-with-eureka: false
fetch-registry: false
Question 12: Comment enregistrer un service dans Eureka?
Réponse:
<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/
Question 13: Comment appeler un autre service avec RestTemplate et load balancing?
Réponse:
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Service
public class OrderService {
private final RestTemplate restTemplate;
public User getUser(Long id) {
// Utilise le nom du service, pas l'URL
return restTemplate.getForObject(
"http://user-service/api/users/" + id, User.class);
}
}
Question 14: Comment utiliser OpenFeign pour les appels inter-services?
Réponse:
@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());
// ...
}
}
Question 15: Comment configurer Spring Cloud Config Server?
Réponse:
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication { }
server:
port: 8888
spring:
cloud:
config:
server:
git:
uri: https://github.com/org/config-repo
default-label: main
Question 16: Comment un service client utilise Config Server?
Réponse:
# bootstrap.yml
spring:
application:
name: user-service
cloud:
config:
uri: http://localhost:8888
Le service récupère user-service.yml depuis le Config Server.
Question 17: Comment configurer Spring Cloud Gateway?
Réponse:
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
Question 18: Comment ajouter un filtre global dans Gateway?
Réponse:
@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;
}
}
Question 19: Comment configurer Resilience4j Circuit Breaker?
Réponse:
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");
}
Question 20: Comment configurer le retry avec Resilience4j?
Réponse:
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);
}
Questions 21-30: Patterns Avancés
Question 21: Comment implémenter un fallback avec Feign?
Réponse:
@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");
}
}
Question 22: Comment implémenter le rate limiting dans Gateway?
Réponse:
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()
);
}
Question 23: Comment rafraîchir la configuration à chaud?
Réponse:
@RefreshScope
@RestController
public class ConfigController {
@Value("${app.message}")
private String message;
@GetMapping("/message")
public String getMessage() {
return message;
}
}
# Déclencher le refresh
curl -X POST http://localhost:8080/actuator/refresh
Ou avec Spring Cloud Bus pour propager à tous les services.
Question 24: Comment tracer les requêtes distribuées?
Réponse: Avec 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
Chaque requête a un traceId unique propagé entre services.
Question 25: Comment sécuriser les communications inter-services?
Réponse:
- mTLS: certificats mutuels
- JWT propagation: token passé entre services
- Service mesh: Istio, Linkerd
- Network policies: Kubernetes
// JWT propagation avec Feign
@Configuration
public class FeignConfig {
@Bean
public RequestInterceptor authInterceptor() {
return template -> {
String token = SecurityContextHolder.getContext()
.getAuthentication().getCredentials().toString();
template.header("Authorization", "Bearer " + token);
};
}
}
Question 26: Comment gérer les secrets en microservices?
Réponse:
- Spring Cloud Config avec encryption
- Vault (HashiCorp)
- Kubernetes Secrets
- AWS Secrets Manager / Azure Key Vault
# Config Server avec encryption
spring:
cloud:
config:
server:
encrypt:
enabled: true
encrypt:
key: ${ENCRYPT_KEY}
Question 27: Comment gérer les versions d'API?
Réponse:
- URL versioning:
/api/v1/users - Header versioning:
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 { }
Question 28: Comment déployer des microservices avec Kubernetes?
Réponse:
# 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
Question 29: Comment monitorer les microservices?
Réponse:
- Métriques: Prometheus + Grafana
- Logs: ELK Stack (Elasticsearch, Logstash, Kibana)
- Traces: Zipkin / Jaeger
- Alerting: Prometheus Alertmanager
Dashboard centralisé avec:
- Latence par service
- Taux d'erreur
- Throughput
- Dépendances
Question 30: Quelles sont les bonnes pratiques microservices?
Réponse:
- Bounded context: un service = un domaine métier
- Database per service: pas de DB partagée
- API contracts: OpenAPI/Swagger
- Idempotence: opérations répétables sans effet
- Healthchecks: Actuator pour chaque service
- Circuit breakers: protection contre les pannes
- Async communication: préférer quand possible
- Centralized logging: corrélation par traceId
- Infrastructure as Code: Terraform, Helm
- Feature flags: déploiement progressif
Score
| Score | Niveau |
|---|---|
| 27-30 | Excellent - Microservices maîtrisés |
| 21-26 | Bien - Quelques révisions |
| 15-20 | Moyen - Relisez les chapitres |
| Moins de 15 | À revoir |