0Pricing
PHP Academy · Leçon

Du monolithe aux microservices

Décidez quoi scinder et comment définir les frontières entre services.

Du monolithe aux microservices est une leçon PHP Academy gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage PHP Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours PHP Academy comprend 4 leçons au total.

Du monolithe aux microservices

Les microservices sont un choix organisationnel et opérationnel, pas une solution par défaut. Découper un monolithe PHP remplace la simplicité des appels internes par des appels réseau, des données distribuées et une complexité de déploiement. Si vous le faites pour de mauvaises raisons, tout devient plus lent.

Cette leçon porte sur la partie la plus difficile : définir les limites des services. Si le découpage est juste, le reste relève de la plomberie ; s'il est mauvais, vous construisez un monolithe distribué — tous les coûts, aucun avantage.

Pourquoi (et pourquoi ne pas) découper

Bonnes raisons de découper :

  • Déploiement indépendant et responsabilité propre à chaque équipe.
  • Mise à l'échelle indépendante des sous-systèmes fortement sollicités.
  • Isolation de la technologie et de l'environnement d'exécution, ainsi que confinement des défaillances.

Mauvaises raisons : « le code est désordonné » (refactorez d'abord le monolithe) ou la volonté de suivre une tendance. Si deux services doivent toujours être déployés ensemble ou partager une table de base de données, il s'agit d'un seul service sous deux casquettes.

Contextes délimités

La conception pilotée par le domaine fournit l'outil le plus précis pour définir les limites : le contexte délimité. Au sein d'un contexte, les termes ont un sens précis et unique. « Client » dans la facturation (la cible d'une facture) diffère de « Client » dans l'assistance (l'auteur d'un ticket).

Chaque contexte délimité est un candidat sérieux pour devenir un service. Les limites suivent le langage métier et la manière dont l'organisation communique réellement — c'est la loi de Conway en action.

Forte cohésion, faible couplage

Une bonne limite de service conserve à l'intérieur les éléments qui évoluent ensemble et repousse à l'extérieur ceux qui évoluent indépendamment. Évaluez un découpage proposé en vous demandant :

  • Combien de fonctionnalités nécessitent de toucher deux services à la fois ? (Cela devrait être rare.)
  • À quel point le schéma d'appels entre eux est-il bavard ? (Les appels devraient être à gros grain.)

Si l'implémentation d'une fonctionnalité chevauche constamment une limite, celle-ci n'est pas au bon endroit.

<?php
// Chatty boundary smell: N network calls to render one view
foreach ($order->lineItems as $item) {
    $product = $catalogApi->get($item->productId); // one call PER item!
    $names[] = $product['name'];
}

// Coarse-grained: one batch call across the boundary
$ids   = array_map(fn($i) => $i->productId, $order->lineItems);
$names = $catalogApi->getMany($ids); // single round-trip
echo count($names) . " products in one call\n";

Une base de données par service

La règle incontournable : chaque service est propriétaire de ses données et aucun autre service ne touche à ses tables. Les bases de données partagées recréent le couplage que vous vouliez éliminer en découpant le système — une modification du schéma casse des services sans rapport.

Les requêtes interservices qui étaient une clause SQL JOIN dans le monolithe deviennent donc des appels d'API ou des modèles de lecture répliqués. C'est le prix à payer, et c'est précisément l'objectif.

<?php
// In the monolith: one JOIN across domains
$sql = 'SELECT o.id, c.email
        FROM orders o JOIN customers c ON c.id = o.customer_id';

// After split: Orders service holds only the foreign id;
// it asks the Customers service for the rest (or keeps a local read model).
$order = $orderRepo->find($id);          // local
$customer = $customersApi->get($order->customerId); // network call
echo $order->id . ' / ' . $customer->email . "\n";

Le modèle du figuier étrangleur

Ne réécrivez jamais un monolithe d'un seul coup. Le modèle du figuier étrangleur permet une extraction progressive : acheminez une partie du trafic vers un nouveau service par l'intermédiaire d'une façade ou d'un proxy, développez-le, puis retirez l'ancien chemin de code uniquement lorsque le nouveau le couvre entièrement.

Un proxy inverse (ou une passerelle d'API) se place en amont et décide, pour chaque chemin, d'appeler le monolithe existant ou le nouveau service. La migration progresse capacité par capacité, tout en restant déployable à chaque étape.

<?php
// Facade routing: peel off one capability at a time
function route(string $path): string {
    $migrated = ['/invoices', '/invoices/pdf']; // moved to billing-svc
    foreach ($migrated as $prefix) {
        if (str_starts_with($path, $prefix)) {
            return 'http://billing-svc' . $path;
        }
    }
    return 'http://legacy-monolith' . $path; // everything else, for now
}
echo route('/invoices/pdf'), "\n";
echo route('/users/42'), "\n";

Extraction d'un module

Un ordre d'extraction pragmatique :

  1. Trouvez un module avec peu de dépendances entrantes et une propriété claire des données.
  2. Encapsulez d'abord ses appels internes au processus derrière une interface dans le monolithe.
  3. Déplacez les données dont il est propriétaire dans son propre schéma ou sa propre base de données.
  4. Remplacez l'implémentation de l'interface par un client réseau.
  5. Basculez le trafic par l'intermédiaire de la façade, puis supprimez l'ancien code.

Encapsuler l'interface à l'intérieur du monolithe permet d'abord de réduire les risques liés à l'étape réseau.

<?php
// Step 2: hide the implementation behind a port the monolith calls
interface InvoiceService {
    public function generate(string $orderId): string; // returns invoice id
}

// Today: local class. Tomorrow: HTTP client to billing-svc.
// The monolith's calling code never changes.
final class LocalInvoiceService implements InvoiceService {
    public function generate(string $orderId): string { return 'inv-1'; }
}

Cohérence des données distribuées

Une fois les données séparées, vous perdez les transactions ACID interservices. Adoptez la cohérence éventuelle : les services publient des événements concernant leurs propres données, et les autres construisent des modèles de lecture locaux à partir de ces événements.

Le service Commandes n'interroge pas Clients à chaque requête : il conserve une petite projection (uniquement les champs dont il a besoin), mise à jour par les événements CustomerUpdated. Cela supprime une dépendance à l'exécution et un saut de latence.

<?php
// Orders service keeps a tiny local projection of customer data
function onCustomerUpdated(PDO $db, array $evt): void {
    $db->prepare(
        'INSERT INTO customer_read_model (id, email)
         VALUES (:id, :email)
         ON CONFLICT (id) DO UPDATE SET email = EXCLUDED.email'
    )->execute(['id' => $evt['id'], 'email' => $evt['email']]);
}

Réalité opérationnelle

Les microservices déplacent la complexité du code vers l'exploitation. Avant de découper votre système, vous avez besoin de :

  • Journalisation centralisée et traçage distribué (identifiants de corrélation entre les différents appels).
  • CI/CD par service et déploiements indépendants avec gestion des versions.
  • Vérifications d'état, délais d'attente, nouvelles tentatives et disjoncteurs sur chaque appel.
  • Tests de contrat afin qu'un fournisseur ne puisse pas casser silencieusement un consommateur.

Si votre équipe ne sait pas correctement exploiter un service, dix services seront dix fois pires.

Dimensionnement adapté des services

« Micro » est trompeur : dimensionnez les services selon la capacité métier et la responsabilité de l'équipe, et non selon le nombre de lignes de code. Avec des services trop fins (des services minuscules), une seule fonctionnalité se ramifie en une avalanche d'appels réseau ; avec des services trop gros, vous revenez à un monolithe.

Une bonne règle empirique : un service doit pouvoir être géré par une seule équipe, être déployé indépendamment et couvrir ses cas d'utilisation principaux sans passer par une chaîne synchrone impliquant de nombreux services voisins.

L'alternative du monolithe modulaire

Avant de passer au distribué, envisagez le monolithe modulaire : un seul artefact déployable, mais découpé en interne en modules dotés de limites explicites et de leurs propres schémas, qui communiquent uniquement par des interfaces publiées — sans accès aux tables d'autres modules.

Vous obtenez des limites claires et un refactoring facile, sans le coût des systèmes distribués. Lorsqu'un module a réellement besoin d'une mise à l'échelle ou d'une responsabilité indépendantes, il est déjà structuré pour être extrait à l'aide du modèle du figuier étrangleur. Pour la plupart des équipes, c'est le meilleur premier choix.

<?php
// Modules talk only through interfaces, never each other's tables.
namespace App\Billing;          // owns billing_* tables
interface BillingFacade {
    public function invoiceForOrder(string $orderId): string;
}

namespace App\Sales;            // owns sales_* tables
final class Checkout {
    public function __construct(private \App\Billing\BillingFacade $billing) {}
    // Sales never SELECTs from billing_* directly - only via the facade.
}

Vérification rapide

Reconnaître un mauvais découpage.

Bilan

Bien définir les limites des services :

  • Découpez pour le déploiement, la mise à l'échelle et la responsabilité — pas parce que le code est désordonné.
  • Alignez les limites sur les contextes délimités ; visez une forte cohésion et un faible couplage.
  • Une base de données par service — aucune table partagée ; remplacez les clauses JOIN par des API ou des modèles de lecture.
  • Migrez progressivement avec le modèle du figuier étrangleur.
  • Acceptez la cohérence éventuelle et investissez dans l'exploitation avant de passer à l'échelle.

Ensuite : comment ces services communiquent réellement — REST et gRPC.

Questions Fréquemment Posées

La leçon « Du monolithe aux microservices » est-elle gratuite ?

Oui — le texte complet de « Du monolithe aux microservices » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours PHP Academy, passe à CoddyKit PRO. Le cours PHP Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Du monolithe aux microservices » ?

Décidez quoi scinder et comment définir les frontières entre services. Tu pratiques PHP Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer PHP Academy ?

Aucune expérience préalable n'est requise. PHP Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.

Combien de temps prend la leçon « Du monolithe aux microservices » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon PHP Academy ?

Oui. Chaque leçon PHP Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Du monolithe aux microservices
  2. Communication entre services : REST et gRPC
  3. Passerelles d’API et découverte de services
  4. Résilience : disjoncteurs et nouvelles tentatives
← Retour à PHP Academy