Aller au contenu

Contrats et gateway

Définir les interfaces avant l'implémentation, gouverner le trafic au point d'entree — le socle de toute communication inter-services fiable.


API gateway

L'API gateway est le point d'entree unique vers vos services backend. Il prend en charge les preoccupations transversales pour que vos services n'aient pas à le faire.

graph TD
    Web[Client Web]
    Mobile[Client Mobile]
    Third[API Tierce]

    GW[API Gateway<br/>auth - rate limit - routing - TLS]

    SvcA[Service Orders]
    SvcB[Service Users]
    SvcC[Service Inventory]

    Web --> GW
    Mobile --> GW
    Third --> GW

    GW -->|"route /orders"| SvcA
    GW -->|"route /users"| SvcB
    GW -->|"route /inventory"| SvcC

Responsabilités du gateway

  • Routage : diriger chaque requête vers le bon service selon l'URL, le header ou le sous-domaine
  • Authentification et autorisation : valider le token JWT ou la clé API avant de transmettre
  • Rate limiting : limiter les appels par client pour protéger les services backend
  • TLS termination : gérer HTTPS au niveau du gateway, communication interne en HTTP simple
  • Agrégation : composer plusieurs appels backend en une seule réponse (BFF pattern)
  • Logging et tracing : injecter les correlation IDs, centraliser les logs d'accès

BFF (Backend for Frontend)

Le BFF est un gateway specialise par type de client. Le client mobile a besoin de payloads légers et d'un seul appel pour afficher un écran. Le client web desktop peut tolérer des payloads plus riches. Le BFF compose les appels backend et formate la réponse selon les besoins du client.

graph TD
    Mobile[Client Mobile] --> BFF_M[BFF Mobile]
    Web[Client Web] --> BFF_W[BFF Web]
    Admin[Client Admin] --> BFF_A[BFF Admin]

    BFF_M --> SvcA[Service Orders]
    BFF_M --> SvcB[Service Users]
    BFF_W --> SvcA
    BFF_W --> SvcB
    BFF_W --> SvcC[Service Analytics]
    BFF_A --> SvcA
    BFF_A --> SvcC

Règle : un BFF par expérience utilisateur, pas par plateforme technique. Si le mobile et le web affichent les mêmes écrans, un seul BFF suffit.

Outils

Outil Type Forces
Kong Gateway open source Plugins riches, Lua/Go extensible
NGINX / Envoy Reverse proxy Performance brute, configuration declarative
AWS API Gateway Managed Intégration Lambda, pas d'infra a gérer
Traefik Cloud-native Auto-discovery (Docker, K8s), Let's Encrypt
Apigee Enterprise Governance, monetisation, analytics

Pas de logique métier dans le gateway

L'API gateway ne doit pas contenir de logique métier. Si vous commencez a y écrire des transformations complexes, c'est un signe que la decomposition des services est mauvaise.


Service mesh

Le service mesh déplacé la gestion de la communication inter-services hors du code applicatif, dans des proxies sidecar déployés aux cotes de chaque service.

graph LR
    subgraph "Service A"
        AppA[App A]
        SA[Sidecar proxy]
    end

    subgraph "Service B"
        AppB[App B]
        SB[Sidecar proxy]
    end

    CP[Control Plane<br/>Istio / Linkerd]

    SA <-->|"mTLS"| SB
    CP -.->|"config: retry, circuit break"| SA
    CP -.->|"config: retry, circuit break"| SB
    AppA <--> SA
    AppB <--> SB

Ce que le mesh apporte sans modifier le code applicatif :

  • mTLS automatique : chiffrement et authentification mutuelle entre tous les services
  • Retries et timeouts : configures au niveau du proxy, pas dans le code
  • Circuit breaking : coupe le trafic vers un service defaillant
  • Load balancing : répartition fine (round-robin, least-connections, canary)
  • Tracing distribué : propagation automatique des headers de trace
  • Métriques : latence, taux d'erreur, throughput sans instrumentation applicative

Quand c'est justifie vs overkill

Justifie Overkill
Plus de 10 services avec flux inter-services Moins de 5 services
Besoin de mTLS partout Équipe ops petite ou sans expérience du mesh
Équipe ops capable de maintenir le control plane Besoins couverts par les librairies applicatives
Observabilité fine requise au niveau réseau Environnement simple sans contrainte zero-trust

Coût opérationnel réel

Un service mesh ajoute de la latence (sidecar proxy), de la complexité opérationnelle et des ressources. Ne l'introduisez que si vous avez un besoin concret qu'il résout.


Contrats d'API

Définir le contrat avant l'implémentation (contract-first) permet aux équipes de travailler en parallèle et evite les desaccords d'interpretation.

Contract-first vs code-first

Contract-first : on écrit la spec (OpenAPI, proto, AsyncAPI), on la fait valider par les consommateurs, puis on généré ou implémenté le code.

  • Les équipes consumer et producer travaillent en parallèle
  • La spec est la source de vérité
  • Les breaking changes sont détectées avant le merge

Code-first : on écrit le code et on généré la spec depuis les annotations.

  • Rapide a démarrer, spec synchronisée avec le code
  • La spec reflete l'implémentation plutôt que le besoin du consommateur
  • Moins adapté aux APIs publiques

Recommandation : contract-first pour les APIs exposees a des équipes externes ou des clients tiers. Code-first acceptable pour les APIs internes a une même équipe quand la velocite prime.

Formats de contrat

Format Protocole Forces
OpenAPI 3.x REST Documentation auto, code génération, écosystème
Protobuf gRPC Typage fort, performance, backward compatibility
AsyncAPI Messaging Documentation des événements, code génération
GraphQL SDL GraphQL Schéma type, introspection, fédération

Consumer-driven contracts (Pact)

Le problème classique : le producer change son API et casse les consumers sans le savoir. Les tests d'intégration de bout en bout sont lents et fragiles. Les consumer-driven contracts inversent la responsabilité.

sequenceDiagram
    participant C as Consumer
    participant PB as Pact Broker
    participant P as Producer

    C->>PB: 1. publie ses attentes (pact file)
    Note over C: "je m'attends a GET /users/1<br/>retourne {id, name, email}"
    P->>PB: 2. recupere les pacts
    P->>P: 3. verifie que son API satisfait les pacts
    P-->>PB: 4. publie le resultat de verification
    PB-->>C: 5. le consumer sait si le deploy est safe

Le flux Pact :

  1. Le consumer écrit un test qui décrit ce qu'il attend du producer (requête + réponse minimale)
  2. Ce test généré un fichier pact (JSON) publie sur le Pact Broker
  3. Le producer récupéré les pacts et les rejoue contre son API
  4. Si tous les pacts passent, le producer peut déployer sans casser ses consumers

Avantage clé : le consumer ne teste que ce qu'il utilisé. Si le producer ajoute un champ, aucun pact ne casse. Si le producer supprimé un champ utilisé, le pact échoué avant le merge.

{
  "consumer": { "name": "OrderUI" },
  "provider": { "name": "UserService" },
  "interactions": [
    {
      "description": "get user by id",
      "request": {
        "method": "GET",
        "path": "/users/usr-001"
      },
      "response": {
        "status": 200,
        "body": {
          "id": "usr-001",
          "name": "Alice Martin",
          "email": "alice@example.com"
        }
      }
    }
  ]
}

API versioning

Les APIs evoluent. Les consumers existants ne doivent pas casser à chaque changement. La stratégie de versioning définit comment cohabitent les anciennes et nouvelles versions.

Stratégies de versioning

Stratégie Exemple Avantage Inconvénient
URL path /v1/orders, /v2/orders Explicite, facile à router Duplication de routes
Header Accept: application/vnd.api.v2 URL propre Moins visible, debug difficile
Query parameter /orders?version=2 Simple a implémenter Pollue l'URL, cache complique
Content negociation Accept: application/json;v=2 Standard HTTP Support client inegal

Recommandation : URL path pour les APIs publiques (clarte, routage simple, documentation evidente). Header pour les APIs internes quand la gouvernance est mature.

Breaking vs non-breaking changes

Non-breaking (safe) Breaking (casse les consumers)
Ajouter un champ optionnel Supprimer un champ
Ajouter un endpoint Renommer un champ
Ajouter une valeur d'enum Changer le type d'un champ
Relacher une validation Rendre obligatoire un champ optionnel
Ajouter un header optionnel Changer un code de retour

Deprecation policy

Ne jamais supprimer une version sans prévenir. Un cycle de deprecation standard :

  1. Announce : documenter la deprecation (header Deprecation, changelog, email)
  2. Sunset header : Sunset: Sat, 01 Nov 2025 00:00:00 GMT — date de fin de support
  3. Monitoring : mesurer le trafic sur la version deprecee pour identifier les consumers restants
  4. Grâce period : maintenir la version au minimum 6 mois après l'annonce (12 mois pour les APIs publiques)
  5. Shutdown : retourner 410 Gone avec un lien vers la nouvelle version
HTTP/1.1 200 OK
Deprecation: true
Sunset: Sat, 01 Nov 2025 00:00:00 GMT
Link: </v3/orders>; rel="successor-version"

Évolution avec Protobuf

Protobuf offre la meilleure compatibilité ascendante et descendante parmi les formats :

  • Les champs sont identifiés par numéro, pas par nom
  • Ajouter un champ = nouveau numéro, les anciens clients ignorent le champ inconnu
  • Supprimer un champ = marquer le numéro reserved
  • Les clients anciens et nouveaux coexistent naturellement
message Order {
  string id = 1;
  string customer_id = 2;
  OrderStatus status = 3;
  // champ supprime : ne jamais reutiliser le numero 4
  reserved 4;
  // nouveau champ : les anciens clients l'ignorent
  string tracking_url = 5;
}

Versionner les événements aussi

Les événements asynchrones (Kafka, RabbitMQ) doivent être versionnes avec la même rigueur que les APIs REST. Un événement OrderCreated_v1 et OrderCreated_v2 peuvent coexister sur le même topic. Le consumer géré les deux versions ou migré. AsyncAPI formalise ces contrats.


Gouvernance des APIs

Sans gouvernance, les APIs proliferent avec des conventions différentes, des versions non documentees et des contracts implicites.

Catalogue d'APIs

Un registre centralise de toutes les APIs du système. Chaque API est documentee avec :

  • Sa spec (OpenAPI, proto, AsyncAPI)
  • Son propriétaire (équipe responsable)
  • Son statut (active, deprecated, sunset)
  • Ses consumers connus
  • Ses SLOs (latence, disponibilité, throughput)

Outils : Backstage (Spotify), SwaggerHub, Apicurio, Postman.

Linting automatique

Valider automatiquement les specs dans la CI pour imposer les conventions :

  • Nommage cohérent (camelCase vs snake_case)
  • Codes de retour corrects (201 pour création, 404 pour not found)
  • Pagination obligatoire pour les listes
  • Champs de date au format ISO 8601
  • Réponses d'erreur standardisees (RFC 7807 Problem Détails)

Spectral (Stoplight) permet de définir des règles de linting pour OpenAPI et AsyncAPI.

# .spectral.yaml
rules:
  operation-operationId:
    severity: error
  oas3-valid-media-example:
    severity: warn
  path-keys-no-trailing-slash:
    severity: error

La gouvernance comme enabler

La gouvernance des APIs ne doit pas ralentir les équipes. Automatiser le linting dans la CI, publier automatiquement dans le catalogue, et limiter la revue manuelle aux breaking changes. L'objectif est la cohérence sans le goulot d'étranglement.


Chapitre suivant : Sagas et integration — transactions distribuées, compensations et patterns de fiabilité.