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èreDescriptionExemple
Par domaine métierChaque service représente un bounded context du DDDUser Service, Order Service, Payment Service
Par capacité métierChaque service implémente une capacité organisationnelleFacturation, Inventaire, Notifications
Par subdomainAligné sur les sous-domaines du métierCore (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égorieOptions
Communication synchroneREST, gRPC, GraphQL
Communication asynchroneKafka, RabbitMQ, Amazon SQS, NATS
OrchestrationKubernetes, Docker Swarm, Amazon ECS
Service DiscoveryConsul, Eureka, DNS-based (Kubernetes)
ObservabilitéJaeger, Zipkin, OpenTelemetry, Prometheus
API GatewayKong, 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.