Microservices
Comment décomposer un système en services petits, autonomes et déployables de manière indépendante, alignés sur les domaines métier.
Quel problème cela résout
À mesure qu’une application monolithique grandit, des problèmes surgissent et ralentissent l’équipe :
- Déploiements risqués : Un petit changement nécessite de redéployer toute l’application
- Mise à l’échelle inefficace : Pour mettre à l’échelle une fonctionnalité, il faut mettre à l’échelle l’ensemble du monolithe
- Équipes bloquées : Plusieurs équipes travaillent sur la même base de code et se bloquent mutuellement
- Technologie homogène : L’ensemble du système doit utiliser le même langage, le même framework et la même base de données
- Temps de build croissant : Compiler et tester tout le monolithe prend de plus en plus de temps
Monolithe:
┌─────────────────────────────────┐
│ Aplicación │
│ ┌─────┐ ┌─────┐ ┌──────────┐ │
│ │Users│ │Prods│ │ Orders │ │
│ └─────┘ └─────┘ └──────────┘ │
│ ┌─────────────────────────────┐│
│ │ Base de datos única ││
│ └─────────────────────────────┘│
└─────────────────────────────────┘
Un deploy = todo el sistema
Un fallo = todo el sistema
Comment cela fonctionne
L’architecture microservices décompose le système en services petits et indépendants, chacun responsable d’une capacité métier spécifique. Chaque service :
- Possède sa propre base de données (Database per Service)
- Se déploie de manière indépendante
- Communique avec les autres services via des APIs ou des événements
- Appartient à une équipe spécifique
Microservicios:
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Users │ │ Products │ │ Orders │
│ Service │ │ Service │ │ Service │
│ ┌────┐ │ │ ┌────┐ │ │ ┌────┐ │
│ │ DB │ │ │ │ DB │ │ │ │ DB │ │
│ └────┘ │ │ └────┘ │ │ └────┘ │
└──────────┘ └──────────┘ └──────────┘
│ │ │
└──────── Event Bus ─────────┘
Principes de décomposition
La clé réside dans la manière de diviser le système. Les critères les plus efficaces sont :
| Critère | Description | Exemple |
|---|---|---|
| Par domaine métier | Chaque service représente un bounded context du DDD | User Service, Order Service, Payment Service |
| Par capacité métier | Chaque service implémente une capacité organisationnelle | Facturation, Inventaire, Notifications |
| Par subdomain | Aligné sur les sous-domaines du métier | Core (commandes), Supporting (rapports), Generic (auth) |
Communication entre les services
Les microservices communiquent de deux manières principales :
Synchrone (request-response) :
Order Service ──HTTP/gRPC──► Product Service
"¿Hay stock del producto X?"
← "Sí, 50 unidades"
Asynchrone (événements) :
Order Service ──evento──► Event Bus ──► Inventory Service
"OrderCreated" "Reservar stock"
──► Notification Service
"Enviar email"
Database per Service
Chaque microservice est propriétaire de ses données. Aucun autre service n’accède directement à sa base de données :
✅ Correcto:
Order Service ──API──► User Service
"Dame el nombre del usuario 123"
❌ Incorrecto:
Order Service ──SQL──► User DB
"SELECT name FROM users WHERE id=123"
Cela garantit l’encapsulation et permet à chaque service de choisir la technologie de stockage la plus adaptée (SQL, NoSQL, cache, etc.).
Avantages
- Déploiement indépendant : Chaque service se déploie sans affecter les autres
- Mise à l’échelle granulaire : Ne met à l’échelle que les services qui en ont besoin
- Autonomie des équipes : Chaque équipe est propriétaire de son service de bout en bout
- Diversité technologique : Chaque service peut utiliser le langage et le framework les plus adaptés
- Résilience : Une panne dans un service ne fait pas nécessairement tomber tout le système
- Time to market : De petites équipes peuvent livrer plus rapidement
Trade-offs / Inconvénients
- Complexité distribuée : Le débogage, les tests et le tracing sont nettement plus difficiles
- Cohérence éventuelle : Les transactions distribuées sont complexes (elles nécessitent des Sagas, l’Outbox)
- Latence réseau : La communication entre les services ajoute de la latence
- Surcharge opérationnelle : Plus de services = plus de déploiements, plus de supervision, plus d’infrastructure
- Duplication de données : Chaque service peut avoir besoin de copies des données d’autres services
- Complexité organisationnelle : Nécessite des équipes matures dotées d’une culture DevOps
Quand l’utiliser
- Systèmes de grande taille avec plusieurs équipes de développement
- Lorsque différentes parties du système ont des besoins de mise à l’échelle très différents
- Lorsque vous devez déployer des fonctionnalités de manière indépendante et fréquente
- Organisations avec des équipes autonomes alignées sur les domaines métier
- Systèmes où la résilience et la disponibilité sont critiques
Quand l’éviter
- Petites équipes (moins de 8 à 10 développeurs) où la surcharge ne se justifie pas
- Systèmes avec un domaine simple qui ne nécessite pas de décomposition
- Lorsque vous ne disposez pas d’une infrastructure de CI/CD, de supervision et d’orchestration mature
- Prototypes ou MVPs où la vitesse de développement est prioritaire
- Lorsque vous ne pouvez pas définir de bounded contexts clairs (signe que le domaine n’est pas bien compris)
Technologies et implémentations courantes
| Catégorie | Options |
|---|---|
| Communication synchrone | REST, gRPC, GraphQL |
| Communication asynchrone | Kafka, RabbitMQ, Amazon SQS, NATS |
| Orchestration | Kubernetes, Docker Swarm, Amazon ECS |
| Service Discovery | Consul, Eureka, DNS-based (Kubernetes) |
| Observabilité | Jaeger, Zipkin, OpenTelemetry, Prometheus |
| API Gateway | Kong, Traefik, AWS API Gateway |
Relation avec d’autres patterns
- DDD (Domain-Driven Design) : Fournit les critères pour définir les limites de chaque service
- API Gateway : Point d’entrée unique pour les clients externes
- Saga Pattern : Gère les transactions qui traversent plusieurs services
- Event-Driven Architecture : Pattern de communication asynchrone entre les services
- Circuit Breaker : Protège les services des pannes en cascade
Prochaines étapes
Les microservices constituent un style architectural puissant mais exigeant. Pour comprendre comment gérer la communication asynchrone entre eux, explorez l’Event-Driven Architecture. Pour protéger la communication avec des systèmes externes, consultez l’Anti-Corruption Layer.