Passerelles d’API et découverte de services
Acheminez, agrégez et localisez les services dynamiquement.
Passerelles d’API et découverte de services est une leçon PHP Academy gratuite sur CoddyKit. Ceci est la leçon 3 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.
Passerelles et découverte
Une fois que vous avez une douzaine de services, deux problèmes apparaissent. Les clients ne devraient pas avoir à connaître l'adresse de chaque service ni à en appeler cinq pour afficher un écran : c'est le rôle de la passerelle d'API. Et les services qui augmentent ou réduisent leur capacité et changent d'adresse IP ont besoin d'un moyen de se trouver : c'est la découverte de services.
Cette leçon couvre ces deux aspects, avec PHP à la périphérie de la passerelle.
Rôle d'une passerelle d'API
Une passerelle d'API est un point d'entrée unique placé devant vos services. Ses responsabilités habituelles sont les suivantes :
- Routage des requêtes vers le bon service en aval.
- Préoccupations transversales : authentification, limitation du débit, CORS, terminaison TLS.
- Agrégation : composer plusieurs appels aux services en aval en une seule réponse pour le client.
- Traduction de protocole : REST externe en entrée, gRPC interne en sortie.
Elle simplifie les clients et centralise les règles que vous auriez autrement dupliquées dans chaque service.
Routage à la périphérie
À la base, une passerelle associe un chemin entrant à un service en aval. Les passerelles de production (Kong, Traefik, Nginx, AWS API Gateway) le font de manière déclarative, mais la logique est suffisamment simple pour être illustrée en PHP.
<?php
$routes = [
'#^/api/orders#' => 'http://orders-svc',
'#^/api/customers#' => 'http://customers-svc',
'#^/api/catalog#' => 'http://catalog-svc',
];
function resolveUpstream(string $path, array $routes): ?string {
foreach ($routes as $pattern => $upstream) {
if (preg_match($pattern, $path)) {
return $upstream . $path;
}
}
return null; // 404 at the gateway
}
echo resolveUpstream('/api/orders/42', $routes), "\n";Centraliser l'authentification
Validez l'appelant une seule fois au niveau de la passerelle, puis transmettez une identité de confiance en aval afin que chaque service n'ait pas à revérifier le jeton brut. La passerelle vérifie la signature et l'expiration du JWT, puis injecte des en-têtes tels que X-User-Id dans la requête interne (sur un réseau de confiance).
<?php
function authenticate(string $authHeader): ?array {
if (!str_starts_with($authHeader, 'Bearer ')) return null;
$jwt = substr($authHeader, 7);
$claims = verifyJwt($jwt); // signature + exp check
if ($claims === null) return null;
// Forward minimal trusted identity to internal services
return ['X-User-Id' => $claims['sub'], 'X-Scopes' => implode(',', $claims['scopes'])];
}
function verifyJwt(string $j): ?array { return ['sub' => 'u-7', 'scopes' => ['orders:read']]; }
print_r(authenticate('Bearer abc.def.ghi'));Agrégation des réponses
Un écran mobile peut nécessiter les données d'une commande, d'un client et d'un catalogue. Plutôt que de demander au client d'effectuer trois appels, la passerelle les lance, attend les résultats, puis les fusionne. Pour que cela reste rapide, lancez les appels en aval simultanément (promesses Guzzle / curl_multi) plutôt que séquentiellement.
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
use GuzzleHttp\Promise\Utils;
$http = new Client(['timeout' => 2.0]);
$promises = [
'order' => $http->getAsync('http://orders-svc/orders/42'),
'customer' => $http->getAsync('http://customers-svc/customers/7'),
'catalog' => $http->getAsync('http://catalog-svc/items?order=42'),
];
$results = Utils::settle($promises)->wait(); // run in parallel
// merge the fulfilled bodies into one response for the clientServices en aval pour les interfaces
Une passerelle générique ne peut souvent pas répondre aussi bien aux besoins d'une application web, d'une application mobile et de partenaires : chacun souhaite des agrégations et des structures de données différentes. Le modèle Backend pour Frontend (BFF) donne à chaque type de client sa propre passerelle légère, adaptée à ses besoins, tandis que les services partagés restent génériques.
Cela évite une passerelle toute-puissante hypertrophiée et permet à chaque équipe cliente d'évoluer indépendamment.
Le problème de la découverte
Dans un environnement dynamique, les instances apparaissent et disparaissent, et leurs adresses IP changent. Écrire en dur http://10.0.3.14:8080 est fragile. La découverte de services tient à jour un registre indiquant « quelles instances saines du service X existent actuellement », afin que les appelants résolvent un nom logique en adresse réelle au moment de l'appel.
Découverte côté client ou côté serveur
Deux modèles existent :
- Côté client — l'appelant interroge un registre (Consul, etcd), choisit lui-même une instance et assure son propre équilibrage de charge.
- Côté serveur — l'appelant s'adresse à une adresse virtuelle stable (un équilibreur de charge ou un service Kubernetes) qui effectue pour lui la résolution et l'équilibrage.
Dans Kubernetes, vous bénéficiez généralement de la découverte côté serveur gratuitement : appelez http://customers-svc, et le DNS du cluster ainsi que le service Kubernetes s'occupent du reste. En dehors de Kubernetes, les registres de type Consul sont courants.
Interroger un registre
Avec la découverte côté client, l'appelant PHP demande au registre les instances saines et en choisit une. Le registre ne renvoie que les instances qui réussissent les contrôles de santé ; les nœuds défaillants sont donc exclus automatiquement.
<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
function discover(Client $http, string $service): string {
// Consul: only passing-health instances
$res = $http->get("http://consul:8500/v1/health/service/$service?passing=true");
$nodes = json_decode((string) $res->getBody(), true);
if (!$nodes) throw new \RuntimeException("No healthy $service");
$pick = $nodes[array_rand($nodes)]['Service']; // simple LB
return "http://{$pick['Address']}:{$pick['Port']}";
}Contrôles de santé et enregistrement
La découverte n'est fiable que dans la mesure où ses données de santé le sont. Chaque service expose un point de terminaison /health qui vérifie ses dépendances réelles (base de données, cache), puis s'enregistre lui-même (ou est enregistré par la plateforme) au démarrage. Le registre sonde ce point de terminaison et retire les instances qui échouent.
Rendez le contrôle de santé pertinent : renvoyer 200 alors que la base de données est hors service est pire qu'inutile — cela achemine le trafic vers un nœud défaillant.
<?php
// GET /health
function health(PDO $db, Redis $cache): array {
$checks = [
'db' => safe(fn() => $db->query('SELECT 1') !== false),
'cache' => safe(fn() => $cache->ping() === '+PONG'),
];
$ok = !in_array(false, $checks, true);
http_response_code($ok ? 200 : 503);
return ['status' => $ok ? 'pass' : 'fail', 'checks' => $checks];
}
function safe(callable $c): bool { try { return (bool) $c(); } catch (\Throwable) { return false; } }Vivacité ou préparation
Un seul point de contrôle de santé ne suffit pas : distinguez deux questions :
- Vivacité : « le processus est-il actif ? » En cas d'échec, l'orchestrateur redémarre le conteneur. Gardez ce contrôle léger et sans dépendances, sinon une base de données instable déclenchera des redémarrages inutiles.
- Préparation : « peut-il traiter du trafic immédiatement ? » En cas d'échec, le trafic est retenu, mais le processus continue de fonctionner (par exemple pendant le préchargement d'un cache ou lorsque la base de données est temporairement inaccessible).
Les confondre provoque des boucles de redémarrage ou un routage vers des nœuds qui ne sont pas encore prêts.
<?php
// GET /livez - is the process itself healthy? (no external deps)
function livez(): void { http_response_code(200); echo 'alive'; }
// GET /readyz - should we receive traffic? (checks dependencies)
function readyz(PDO $db): void {
try { $db->query('SELECT 1'); http_response_code(200); echo 'ready'; }
catch (\Throwable) { http_response_code(503); echo 'not ready'; }
}Vérification rapide
Réduire les allers-retours du client.
Récapitulatif
Routage et localisation des services :
- Une passerelle d'API centralise le routage, l'authentification, la limitation du débit, TLS et l'agrégation.
- Agrégez simultanément ; utilisez des BFF lorsque les besoins des clients divergent.
- La découverte de services convertit les noms logiques en instances actives et saines.
- Découverte côté client (interroger un registre) ou côté serveur (LB stable ou service Kubernetes).
- Des contrôles de santé pertinents maintiennent le trafic à l'écart des nœuds défaillants.
Ensuite : rendre tous ces appels robustes lorsque certaines parties tombent inévitablement en panne.
Questions Fréquemment Posées
La leçon « Passerelles d’API et découverte de services » est-elle gratuite ?
Oui — le texte complet de « Passerelles d’API et découverte de services » 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 « Passerelles d’API et découverte de services » ?
Acheminez, agrégez et localisez les services dynamiquement. 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 3 sur 4.
Combien de temps prend la leçon « Passerelles d’API et découverte de services » ?
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
- Du monolithe aux microservices
- Communication entre services : REST et gRPC
- Passerelles d’API et découverte de services
- Résilience : disjoncteurs et nouvelles tentatives