1. Introduction : Pourquoi l’API Gateway est indispensable aux microservices
Dans une architecture distribuée, laisser les applications clientes (navigateurs web, applications mobiles, intégrations partenaires) communiquer directement avec des dizaines de microservices internes constitue un anti-pattern majeur.
Le modèle d’accès direct engendre de graves faiblesses architecturales :
- Couplage fort entre clients et services : Tout renommage, découpage ou migration de service oblige à redéployer l’ensemble des clients mobiles et web.
- Surface d’attaque démesurée : Chaque microservice se retrouve exposé sur l’Internet public, fragmentant les règles de pare-feu, les politiques CORS et la gestion des certificats TLS.
- Duplication des fonctions transverses : Chaque équipe réimplémente sa propre logique de validation JWT, de limitation de débit et de traçabilité, introduisant failles et incohérences.
- Latence réseau accumulée : Un smartphone doit exécuter plus de dix requêtes HTTP séquentielles pour composer un seul écran utilisateur.
Accès direct vs Modèle API Gateway
==================================
Accès direct (Anti-pattern) :
[Application Mobile] ──┬──► [Service Auth :8081]
├──► [Service Commandes :8082]
├──► [Service Paiements :8083]
└──► [Service Stocks :8084]
Modèle API Gateway (Recommandé) :
┌────────────────────────────────────────────────────────┐
│ API Gateway (:443) │
│ - Terminaison SSL & Politiques CORS │
│ - Validation JWT & Injection de contexte sécurisé │
│ - Rate Limiting distribué avec Redis (Token Bucket) │
│ - Routage dynamique, délais d'expiration & disjoncteur│
└──────────────────────────┬─────────────────────────────┘
│ Réseau privé VPC (mTLS)
┌────────────────────┼────────────────────┐
▼ ▼ ▼
[Service Auth] [Service Commandes] [Service Paiements]
L’API Gateway sert de point d’entrée unique (reverse proxy) à la frontière du système, centralisant le traitement des préoccupations transversales.
2. Capacités fondamentales d’une passerelle d’entreprise
Une API Gateway de production doit exécuter les responsabilités suivantes avec une latence sub-milliseconde :
| Couche fonctionnelle | Rôle de l’API Gateway | Mécanismes et protocoles |
|---|---|---|
| Reverse Proxy & Routage | Acheminer les requêtes externes vers les microservices privés | Correspondance de préfixes, expressions régulières, pondération canari |
| Authentification en périphérie | Valider cryptographiquement les jetons entrants | Validation JWT RS256/EdDSA, rotation JWKS, mTLS |
| Gouvernance & Rate Limiting | Protéger les services contre les attaques DoS et appliquer les quotas | Algorithme Token Bucket distribué avec Redis |
| Résilience système | Empêcher les pannes en cascade lors d’incidents partiels | Délais d’expiration (timeouts), retries avec backoff exponentiel, disjoncteur (circuit breaker) |
| Traçabilité distribuée | Garantir la visibilité de bout en bout des requêtes | Norme W3C TraceContext (traceparent), OpenTelemetry |
| Transcodage de protocoles | Découpler les protocoles externes des normes internes | Conversion HTTP/1.1・HTTP/2 externe vers gRPC/Protobuf interne |
3. Authentification et défense en profondeur (Defense in Depth)
Règle d’or : L’authentification à la passerelle ne dispense pas de l’autorisation aval
Une erreur critique consiste à considérer que « puisque le jeton JWT a été validé par la passerelle, les microservices internes n’ont plus besoin de vérifier les autorisations ».
Si la passerelle est compromise ou contournée depuis le réseau privé, les microservices se retrouvent sans défense. Le principe de défense en profondeur s’impose :
Flux d'authentification en défense en profondeur
------------------------------------------------
[Client]
│ 1. Authorization: Bearer <JWT>
▼
[API Gateway]
│ 2. Valide la signature cryptographique du JWT via le jeu de clés JWKS local
│ 3. Vérifie l'expiration (exp) et l'émetteur (iss) ; rejette immédiatement les requêtes invalides (401)
│ 4. Extrait les informations validées et les injecte dans des en-têtes internes fiables :
│ - X-User-Id: 98412
│ - X-User-Roles: billing_admin,user
│ - X-Tenant-Id: tenant_corp_a
▼
[Microservice interne (Commandes/Paiements)]
│ 5. Valide la connexion mTLS prouvant l'origine de l'API Gateway
│ 6. Applique sa propre logique d'autorisation métier selon le rôle indiqué dans X-User-Roles
│ 7. Exécute l'opération métier
4. Rate Limiting distribué : Algorithme Token Bucket sous Redis
Un compteur en mémoire locale devient inefficace dès que les conteneurs de l’API Gateway s’adaptent dynamiquement à la charge (HPA). En passant de 2 à 20 instances, le quota accordé aux clients est multiplié par dix.
L’exécution de scripts Lua atomiques sur un cluster Redis central garantit l’intégrité absolue des quotas :
-- Redis Token Bucket Rate Limiting (Script Lua atomique)
-- KEYS[1]: Clé de limitation (ex: ratelimit:tenant_123:orders)
-- ARGV[1]: Capacité maximale du seau (Burst)
-- ARGV[2]: Vitesse de remplissage (Jetons / Seconde)
-- ARGV[3]: Timestamp Unix actuel (secondes)
-- ARGV[4]: Nombre de jetons demandés (généralement 1)
local key = KEYS[1]
local capacity = tonumber(ARGV[1])
local fill_rate = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
local requested = tonumber(ARGV[4])
local data = redis.call('HMGET', key, 'tokens', 'last_updated')
local tokens = tonumber(data[1])
local last_updated = tonumber(data[2])
if not tokens then
tokens = capacity
last_updated = now
else
local elapsed = math.max(0, now - last_updated)
tokens = math.min(capacity, tokens + (elapsed * fill_rate))
last_updated = now
end
if tokens >= requested then
tokens = tokens - requested
redis.call('HMSET', key, 'tokens', tokens, 'last_updated', last_updated)
redis.call('EXPIRE', key, math.ceil(capacity / fill_rate) * 2)
return {1, math.floor(tokens)} -- 1 = Accordé
else
redis.call('HMSET', key, 'tokens', tokens, 'last_updated', last_updated)
return {0, 0} -- 0 = Rejeté (429 Too Many Requests)
end
5. Modèles de résilience : Timeouts, Retries et Circuit Breakers
- Délais d’expiration stricts : Le timeout configuré sur la passerelle pour attendre un microservice doit impérativement être plus court que le délai interne du microservice, évitant l’épuisement des pools de connexions.
- Politique de réessai idempotente : Seules les requêtes idempotentes (GET, PUT, DELETE) peuvent faire l’objet de nouvelles tentatives automatiques. Réessayer aveuglément un POST de paiement provoque des débits multiples.
- Disjoncteur (Circuit Breaker) : Dès qu’un service génère plus de 50% d’erreurs, le disjoncteur bascule en état OPEN pour bloquer les requêtes entrantes et renvoyer une réponse de dégradation.
6. Comparatif technique : Envoy vs NGINX vs Kong
| Critère | Envoy Proxy | NGINX (Open Source / Plus) | Kong Gateway |
|---|---|---|---|
| Langage de base | C++ (Faible latence et maîtrise mémoire) | C (Modèle événementiel robuste) | Lua / OpenResty (Noyau NGINX) |
| Mise à jour configuration | Dynamique via xDS API sans rechargement | Statique via rechargement des processus | Dynamique via API REST et outil decK |
| Protocoles supportés | HTTP/1.1, HTTP/2, HTTP/3, gRPC | HTTP/1.1, HTTP/2, gRPC reverse proxy | HTTP/1.1, HTTP/2, gRPC |
| Extensibilité | Filtres WebAssembly (Wasm) et C++ | Modules C, njs | Plugins Lua et Wasm |
| Cas d’usage privilégié | Cloud Native, Ingress Kubernetes | Distribution statique, proxy inverse simple | Gestion d’API en entreprise |
7. API Gateway et Service Mesh
- API Gateway (Trafic Nord-Sud) : Gère le trafic entrant de l’extérieur vers le réseau privé (authentification client, facturation, quotas et versioning d’API).
- Service Mesh (Trafic Est-Ouest) : Pilote la communication entre microservices internes (Istio, Linkerd), assurant le chiffrement mTLS automatique et le routage fin des versions applicatives.