L’extraction : un module quitte le monolithe et devient un microservice
Département de Mathématiques et Informatique, Faculté des Sciences et Techniques, Université Cheikh Anta Diop de Dakar
Contenu
Le module livraison quitte le monolithe : il devient livraison-service, un microservice FastAPI en Python, extrait selon le pattern Strangler Fig. L’appel qui traversait la JVM traverse désormais le réseau — avec ses promesses (déploiement indépendant, écosystème Python) et ses dangers, que nous éprouverons en provoquant une panne. Au passage : docker compose orchestre nos quatre conteneurs, et une carte Leaflet de Dakar suit le livreur en temps réel.
Le scénario
La direction veut faire évoluer le calcul d’itinéraires : optimisation, trafic, géospatial — le terrain de l’écosystème Python (geopandas, OR-Tools). Et déployer ces évolutions chaque semaine, sans redéployer SénResto.
Les mauvaises raisons existent aussi
« C’est moderne », « Netflix le fait », « le CV »… Un microservice injustifié, c’est tout le coût du réseau sans aucun bénéfice. La charge de la preuve incombe toujours à l’extraction.
Les critères d’un bon candidat à l’extraction, appliqués à nos modules :
| Critère | livraison | contre-exemple |
|---|---|---|
| Frontière déjà nette | oui (Lab 3) | — |
| API étroite | 3 opérations | commandes : au cœur de tout |
| Données peu partagées | les livreurs | catalogue : lu par tous |
| Raison technologique | Python géo | notifications : aucune |
| Raison de déploiement | évolutions fréquentes | partage : jamais |
À retenir
On n’extrait pas « les modules » : on extrait un module, celui dont l’extraction a une raison d’être. Les autres restent — et c’est très bien ainsi. Votre ADR no4 devra défendre ce choix et les non-choix.
La boutique du coin
Un boutiquier veut plus grand. Il ne ferme pas pour tout casser : il construit la nouvelle boutique juste à côté, puis déplace un rayon à la fois. Les clients achètent tous les jours, sans rien remarquer. Un rayon pose problème ? Il le ramène. L’ancienne est vide ? Il la ferme.
livraison-service (Python), construit à côté du monolithe qui continue de tourner ;(Le nom officiel, Strangler Fig, vient d’un arbre. Retenez la boutique.)
Définition (Martin Fowler, 2004)
Plutôt que réécrire d’un bloc (le « big bang », qui échoue presque toujours), on fait pousser le nouveau autour de l’ancien, on migre progressivement, et l’ancien meurt quand plus rien ne l’appelle. À chaque instant, l’application fonctionne.
L’autre méthode — « on ferme, on reconstruit tout, on rouvre dans six mois » — échoue presque toujours. Trois raisons simples :
Les trois règles du figuier
1. Le nouveau se construit à côté, jamais à la place. 2. Chaque bascule peut être annulée — chez nous : un profil Spring. 3. L’ancien code n’est supprimé que quand plus personne ne l’appelle.
livraison du God controller du Lab 1 aurait exigé des semaines d’archéologie. Aujourd’hui, la frontière est déjà tracée, l’API déjà étroite (assigner, liberer, tous), les données déjà isolées.AssignationLivreurs reste en place, même API pour commandes — mais devient une façade qui délègue en HTTP. commandes ne saura jamais que livraison a déménagé.À retenir — la phrase du semestre
« Monolith first, microservices when justified » n’était pas de la prudence : c’était une stratégie. Le monolithe modulaire est le meilleur brouillon d’un système distribué — chaque frontière interne est une extraction en attente, qu’on ne paiera que si elle se justifie.
Quatre mots que ce lab installe pour de bon :
| Latence | le temps aller-retour d’un appel ; 100 ns en JVM, des millisecondes en HTTP — un facteur 10,000 |
|---|---|
| Timeout | la durée maximale qu’on accepte d’attendre avant de déclarer l’échec ; toujours explicite, jamais infini |
| 503 | Service Unavailable : « je vais bien, mais quelqu’un dont je dépends ne répond pas — réessayez » |
| Couplage temporel | deux services qui doivent être vivants au même instant pour coopérer — la vraie dette du synchrone |
À retenir
Un timeout n’est pas un aveu d’échec : c’est une décision d’architecte — combien de temps la confirmation d’une commande a-t-elle le droit de retenir un client ?
Peter Deutsch (Sun, 1994) a listé les huit croyances fausses que tout débutant du distribué paie un jour :
Celles qui nous mordent aujourd’hui
La no1 justifie nos timeouts et le 503 ; la no2, notre réflexion avant chaque extraction ; la no5, l’usage des noms de services dans compose plutôt que des adresses. Les cinq autres vous attendent en entreprise.
Le vrai piège du distribué
Un appel de méthode a deux issues : il réussit, ou il lève une exception. Un appel réseau en a trois : réponse OK, réponse d’erreur… ou pas de réponse du tout. Et dans ce troisième cas, impossible de savoir si l’opération a eu lieu côté serveur — le livreur a-t-il été réservé ? Vous ne le savez pas.
À retenir
La latence est 10,000 fois supérieure et l’échec devient un cas normal. Un microservice, c’est un module qui a accepté ce contrat — c’est pour cela qu’on n’extrait pas sans raison.
L’API du module devient une API HTTP — traduction presque mot à mot :
POST /assignations {"quartier": "Medina", "restaurant_quartier": "Ouakam"}
200 {"livreur_id": 1, "livreur_nom": "Ibrahima Ndiaye", "eta_minutes": 43}
409 {"erreur": "Aucun livreur disponible pour le moment, ..."}
DELETE /assignations/1 # liberer le livreur 1
GET /livreurs # la liste (pour l'onglet Livreurs)
GET /livreurs/1/position # {"latitude": ..., "longitude": ...} (carte)livreur consultée par le monolithe.
services:
postgres: # les donnees du monolithe
image: postgres:16
backend: # Spring Boot, profil "distribue"
build: ./backend
environment:
- SPRING_PROFILES_ACTIVE=distribue
- LIVRAISON_URL=http://livraison-service:8001
livraison-service: # FastAPI
build: ./livraison-service
frontend: # React + la carte
build: ./frontendhttp://livraison-service:8001 — pas d’IP, pas de configuration réseau manuelle.docker compose up --build. Et un seul pour la panne de tout à l’heure : docker compose stop livraison-service…react-leaflet l’intègre à notre frontend en un composant.En pratique au lab
L’onglet « Carte » montre les restaurants (marqueurs fixes) et le livreur de la commande suivie (marqueur mobile). Quartiers, coordonnées : tout vient de QuartiersDakar — désormais propriété du service Python.
Point de départ : votre lab3-final. Et en clôture, une expérience dont le Lab 5 fera son affaire : docker compose stop livraison-service.
| Rôle | Pilotage au Lab 4 |
|---|---|
| Le Doyen | merges, tags, ADR — et l’expérience de la panne au vidéoprojecteur |
| L’Huissier | les profils Spring (monolithe / distribué) et docker compose |
| Le Rédacteur | l’onglet Carte (react-leaflet, polling des positions) |
| Le Notaire | la façade HTTP : AdaptateurLivraisonHttp (RestClient, timeouts) |
| L’Appariteur | le service FastAPI : assignations, positions, données livreurs |
Le livrable individuel de la séance
L’Architecte du jour signe l’ADR no4 : « Pourquoi extraire Livraison — et pourquoi pas les autres ? » — le premier ADR qui doit défendre des non-décisions.
À retenir
La question qui ouvre la séance 5
En fin de lab, nous tuerons livraison-service… et la confirmation de commande mourra avec lui. Un service peut-il tomber sans entraîner les autres ? Réponse au Lab 5 : l’asynchrone — RabbitMQ, et des événements qui attendent patiemment le retour des absents.