Le modèle Strangler Fig : un moyen sûr de migrer des applications monolithiques
Dans le génie logiciel moderne, les applications monolithiques existantes constituent un défi courant. Au fil du temps, une base de code réussie devient si volumineuse et interconnectée que la réalisation de simples modifications devient risquée, les déploiements prennent des heures et la mise à l’échelle de fonctionnalités individuelles est pratiquement impossible.
Lorsque les équipes décident de moderniser leurs systèmes en migrant vers des microservices, elles sont confrontées à une question à enjeux majeurs : Comment réécrire le système sans interrompre notre activité actuelle ?
Une option est une réécriture « Big Bang » : construire le nouveau système à partir de zéro, derrière des portes closes, et tout basculer en une seule journée. Cependant, cela est extrêmement risqué et conduit souvent à un échec.
Heureusement, il existe une alternative plus sûre et plus fiable : le modèle de figue étrangleur. Dans ce guide, nous explorerons ce qu’est le modèle Strangler Fig, pourquoi il fonctionne et comment l’appliquer étape par étape à l’aide de diagrammes clairs et de code du monde réel.
L’analogie avec le monde réel : la plante de figuier étrangleur
Le motif porte le nom du figuier étrangleur, une plante originaire des forêts tropicales humides.
Une graine de figuier étrangleur germe dans les branches supérieures d’un arbre « hôte » existant. Au lieu de pousser de bas en haut, la figue pousse vers le bas :
- Il envoie les racines le long du tronc de l’arbre hôte jusqu’à ce qu’elles atteignent le sol forestier et s’ancrent dans le sol.
- Au fil du temps, davantage de racines poussent, s’enroulent autour de l’hôte et fusionnent.
- Le figuier produit des feuilles qui empêchent la lumière d’atteindre l’arbre hôte.
- Finalement, l’arbre hôte meurt et pourrit, laissant un figuier étrangleur creux qui se tient fermement à sa place.
Dans l’architecture logicielle, le monolithe hérité est l’arborescence hôte, et les nouveaux microservices sont la figure étrangleur. Nous construisons les nouveaux services autour du monolithe, en éloignant progressivement le trafic du système existant jusqu’à ce que le monolithe puisse être complètement arrêté.
Pourquoi les réécritures de “Big Bang” échouent
Avant de plonger dans les mécanismes du modèle Strangler Fig, comprenons pourquoi l’alternative – une réécriture complète – est si dangereuse :
- Aucune valeur pendant des mois (ou des années) : les développeurs passent beaucoup de temps à écrire du code, mais rien n’est mis en ligne tant que l’ensemble du projet n’est pas terminé.
- Scope Creep : au cours d’une réécriture de deux ans, les besoins de l’entreprise changent. La cible bouge et le nouveau système doit prendre en charge des fonctionnalités qui n’existaient pas au début de la réécriture.
- Comportement implicite manquant : les monolithes contiennent des années de corrections de bugs et de gestions de cas extrêmes non documentées. Une réécriture de table rase oublie souvent ces détails.
- Risque de déploiement élevé : la désactivation d’un ancien système massif et l’activation d’un nouveau en même temps créent un rayon d’explosion considérable en cas de problème.
Comment fonctionne le modèle de figue étrangleur
L’idée centrale du modèle Strangler Fig est la migration incrémentale. Au lieu de migrer l’ensemble du système, vous migrez une petite fonctionnalité ou « tranche » à la fois.
Le processus de migration s’exécute en cinq étapes clés :
1. Identifiez un contexte délimité
Examinez votre monolithe et identifiez une capacité commerciale unique et autonome, facile à extraire. Les bons candidats incluent :
- Des fonctionnalités qui changent fréquemment (l’équipe bénéficie donc rapidement de déploiements indépendants).
- Fonctionnalités simples et à faible risque (comme une FAQ statique ou une section de préférences utilisateur) pour tester le pipeline de migration.
- Fonctionnalités avec des limites de base de données propres et bien définies.
2. Implémenter le nouveau microservice
Développez la capacité identifiée sous la forme d’un tout nouveau microservice moderne. Ce service possède sa propre base de données, son propre pipeline de déploiement et est construit à l’aide de piles technologiques modernes. Surtout, l’ancienne fonctionnalité du monolithe reste active et inchangée pour le moment.
3. Présentez la couche d’interception
Pour rendre la migration transparente pour vos utilisateurs, vous introduisez une couche d’interception (telle qu’une passerelle API ou un proxy inverse) devant l’application. Tout le trafic client va désormais en premier vers cette passerelle.
Initialement, la passerelle achemine 100 % de toutes les requêtes vers le monolithe existant.
4. Transition progressive du trafic
Une fois que le nouveau microservice est entièrement testé et prêt, vous mettez à jour les règles de routage dans la couche d’interception. Au lieu de router les requêtes pour la fonctionnalité migrée (par exemple, /api/users) vers le monolithe, la passerelle les redirige vers le nouveau microservice.
Toutes les autres demandes continuent d’être adressées au monolithe. Si le nouveau service échoue ou présente des bogues, vous pouvez rapidement mettre à jour la passerelle pour renvoyer le trafic vers le monolithe, garantissant ainsi une interruption minimale.
5. Mise hors service et répétition
Une fois que le nouveau microservice fonctionne de manière stable pendant un certain temps, vous pouvez supprimer en toute sécurité le code correspondant dans l’ancien monolithe.
Vous sélectionnez ensuite la fonctionnalité suivante et répétez le processus. Au fil du temps, le monolithe rétrécit jusqu’à ce qu’il ne reste plus de trafic, et vous pouvez mettre complètement hors service l’ancien serveur.
La couche d’interception : exemple de routage express
Le cœur du motif Strangler Fig est la Couche d’interception. Il permet de rediriger les requêtes sans modifier les applications clientes (applications web, applications mobiles).
Voici un exemple pratique de Node.js utilisant un proxy de passerelle basé sur Express. Il achemine les requêtes de manière dynamique : les requêtes entrantes sont dirigées vers les nouveaux services si elles correspondent aux chemins migrés ; sinon, ils retombent sur le monolithe hérité.
const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
const PORT = 8080;
// Configuration: Target server URLs
const LEGACY_MONOLITH_URL = 'http://legacy-monolith-server:3000';
const NEW_USER_SERVICE_URL = 'http://new-user-service:3001';
const NEW_PAYMENT_SERVICE_URL = 'http://new-payment-service:3002';
// Simple logging middleware to track traffic distribution
app.use((req, res, next) => {
console.log(`[ROUTE LOG] Incoming request: ${req.method} ${req.url}`);
next();
});
// 1. MIGRATED: User registration & profile requests route to the new microservice
app.use('/api/users', createProxyMiddleware({
target: NEW_USER_SERVICE_URL,
changeOrigin: true,
pathRewrite: {
'^/api/users': '/v1/users', // Translate path format if necessary
}
}));
// 2. MIGRATED: Payment transactions route to the new payment microservice
app.use('/api/payments', createProxyMiddleware({
target: NEW_PAYMENT_SERVICE_URL,
changeOrigin: true
}));
// 3. FALLBACK: All other legacy routes automatically default to the Monolith
app.use('/', createProxyMiddleware({
target: LEGACY_MONOLITH_URL,
changeOrigin: true
}));
app.listen(PORT, () => {
console.log(`Interception Gateway routing traffic successfully on port ${PORT}`);
});
Gestion de la base de données : la partie la plus difficile
Bien que le routage du trafic API soit relativement simple, la gestion des données constitue l’aspect le plus difficile de la migration monolithique. Un monolithe possède généralement une base de données unique et massive dans laquelle les tables sont fortement jointes.
Lorsque vous extrayez un service, vous devez également extraire ses données. Il existe deux approches courantes pour gérer cela :
- Double écriture : la couche d’interception ou l’application écrit simultanément des données dans la base de données existante et dans la nouvelle base de données de service pendant la phase de transition. Cela maintient les deux bases de données synchronisées.
- Change Data Capture (CDC) : un outil comme Debezium surveille le journal des transactions de la base de données existante et diffuse automatiquement les modifications apportées à la nouvelle base de données de microservices en temps quasi réel.
Une fois que vous êtes sûr que les bases de données sont entièrement synchronisées et que la nouvelle base de données est correcte, vous basculez le trafic de lecture vers le nouveau service et arrêtez les tables héritées.
Comparaison : Big Bang Rewrite contre Strangler Fig
| Caractéristique/métrique | Réécriture du Big Bang | Modèle de figue étrangleur |
|---|---|---|
| Niveau de risque | Extrêmement élevé | Faible et géré |
| Boucle de rétroaction | Très lent (seulement à la fin) | Rapide (tests de production continus) |
| Stratégie de restauration | Difficile (nécessite la restauration des sauvegardes) | Facile (modifier les règles d’itinéraire dans la passerelle) |
| Impact commercial | Perturbateur | Zéro temps d’arrêt |
| Complexité du système | Élevé (pendant la phase de construction) | Élevé (pendant la phase de migration) |
| Temps de déploiement | Sortie massive d’un single | Petites mises à jour fréquentes |
Conclusion
Le modèle Strangler Fig est la norme industrielle pour la migration des monolithes vers les microservices. En remplaçant le code existant progressivement plutôt qu’en une seule fois, vous éliminez le risque d’un échec « Big Bang ».
Il permet de limiter les déploiements, fournit un retour instantané sur le trafic de production réel et permet à votre équipe de continuer à apporter de la valeur commerciale tout au long du cycle de vie de la migration.
Bien que la gestion de la migration des bases de données et l’exécution de deux systèmes parallèles ajoutent une complexité opérationnelle, la sécurité, la prévisibilité et la stabilité qu’elle offre en font le choix privilégié pour les migrations cloud modernes.