0Pricing
PHP Academy · Lezione

API Gateway e individuazione dei servizi

Instradi, aggreghi e individui dinamicamente i servizi

API Gateway e individuazione dei servizi è una lezione PHP Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento PHP Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso PHP Academy include 4 lezioni in totale.

Gateway e individuazione dei servizi

Quando si hanno una dozzina di servizi, emergono due problemi. I client non dovrebbero dover conoscere l'indirizzo di ogni servizio né chiamarne cinque per visualizzare una schermata: questo è il compito dell'API gateway. Inoltre, i servizi che aumentano o riducono la propria capacità e cambiano indirizzo IP hanno bisogno di un modo per trovarsi a vicenda: questo è il compito dell'individuazione dei servizi.

Questa lezione tratta entrambi gli aspetti, con PHP sul perimetro del gateway.

Cosa fa un API gateway

Un API gateway è un unico punto di ingresso davanti ai propri servizi. Le responsabilità tipiche sono:

  • instradare le richieste al backend corretto tramite il routing.
  • gestire le funzionalità trasversali: autenticazione, limitazione della frequenza, CORS, terminazione TLS.
  • eseguire l'aggregazione: combinare diverse chiamate ai backend in un'unica risposta per il client.
  • eseguire la traduzione dei protocolli: REST dall'esterno, gRPC all'interno.

Mantiene semplici i client e centralizza le policy che altrimenti verrebbero duplicate in ogni servizio.

Routing sul perimetro

In sostanza, un gateway associa un percorso in ingresso a un servizio upstream. I gateway di produzione (Kong, Traefik, Nginx, AWS API Gateway) eseguono questa operazione in modo dichiarativo, ma la logica è abbastanza semplice da poter essere illustrata in 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";

Centralizzare l'autenticazione

Si convalida una volta sola il chiamante sul gateway, quindi si inoltra a valle un'identità attendibile, così ogni servizio non deve verificare nuovamente il token originale. Il gateway controlla la firma e la scadenza del JWT e inserisce header come X-User-Id nella richiesta interna (su una rete attendibile).

<?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'));

Aggregazione delle risposte

Una schermata mobile potrebbe aver bisogno dei dati relativi a un ordine, a un cliente e al catalogo. Invece di effettuare tre chiamate dal client, il gateway le esegue in parallelo, attende le risposte e le combina. Per mantenere elevate le prestazioni, si eseguono le chiamate upstream in modo concorrenziale (promise di Guzzle / curl_multi) anziché in sequenza.

<?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 client

Backend per i frontend

Spesso un gateway generico non riesce a servire altrettanto bene un'app web, un'app mobile e i partner: ciascuno richiede aggregazioni e strutture dei payload diverse. Il pattern Backend-for-Frontend (BFF) assegna a ogni tipo di client un gateway sottile e adattato alle sue esigenze, mentre i servizi condivisi rimangono generici.

In questo modo si evita un gateway monolitico e onnipotente e ogni team client può procedere in modo indipendente.

Il problema dell'individuazione

In un ambiente dinamico, le istanze vengono create e rimosse e i loro indirizzi IP cambiano. Codificare direttamente http://10.0.3.14:8080 è fragile. L'individuazione dei servizi mantiene un registro aggiornato delle «istanze integre del servizio X attualmente disponibili», così i chiamanti risolvono un nome logico in un indirizzo reale al momento della chiamata.

Individuazione lato client e lato server

Esistono due modelli:

  • lato client: il chiamante interroga un registro (Consul, etcd), sceglie autonomamente un'istanza ed esegue il proprio bilanciamento del carico.
  • lato server: il chiamante accede a un indirizzo virtuale stabile (un bilanciatore del carico / Kubernetes Service) che risolve e bilancia le richieste al suo posto.

In Kubernetes si ottiene generalmente l'individuazione lato server senza configurazioni aggiuntive: si chiama http://customers-svc e il DNS del cluster e il Service gestiscono il resto. Al di fuori di k8s, sono comuni i registri in stile Consul.

Interrogare un registro

Con l'individuazione lato client, il chiamante PHP chiede al registro quali istanze sono integre e ne sceglie una. Il registro restituisce solo le istanze che superano i controlli di salute, quindi i nodi non disponibili vengono esclusi automaticamente.

<?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']}";
}

Controlli di salute e registrazione

L'individuazione dei servizi è valida solo quanto lo sono i dati sul loro stato di salute. Ogni servizio espone un endpoint /health che verifica le dipendenze effettive (DB, cache) e si registra all'avvio (oppure viene registrato dalla piattaforma). Il registro interroga quell'endpoint ed elimina le istanze che non superano il controllo.

Il controllo di salute deve essere significativo: restituire 200 mentre il database è inattivo è peggio che inutile, perché indirizza il traffico verso un nodo non funzionante.

<?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; } }

Liveness e readiness

Un solo endpoint di salute non basta: occorre distinguere due domande:

  • Liveness: «il processo è attivo?» Se il controllo fallisce, l'orchestratore riavvia il container. Il controllo deve essere rapido e non dipendere da altre risorse, altrimenti un database instabile causa riavvii inutili.
  • Readiness: «il processo può gestire il traffico in questo momento?» Se il controllo fallisce, il traffico viene bloccato, ma il processo continua a funzionare (per esempio mentre una cache si sta riscaldando o il database è temporaneamente irraggiungibile).

Confondere i due aspetti causa cicli di riavvio oppure l'instradamento del traffico verso nodi non ancora pronti.

<?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'; }
}

Verifica rapida

Ridurre i viaggi di andata e ritorno del client.

Riepilogo

Instradare e individuare i servizi:

  • Un API gateway centralizza routing, autenticazione, limitazione della frequenza, TLS e aggregazione.
  • Si esegue l'aggregazione in modo concorrente; si usano i BFF quando le esigenze dei client divergono.
  • L'individuazione dei servizi risolve i nomi logici in istanze attive e integre.
  • Individuazione lato client (interrogazione di un registro) e lato server (bilanciatore stabile / Kubernetes Service).
  • Controlli di salute significativi mantengono il traffico lontano dai nodi non funzionanti.

Prossimo argomento: mantenere resilienti tutte queste chiamate quando alcune parti inevitabilmente falliscono.

Domande Frequenti

La lezione «API Gateway e individuazione dei servizi» è gratuita?

Sì — il testo completo di «API Gateway e individuazione dei servizi» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso PHP Academy, passa a CoddyKit PRO. Il corso PHP Academy include 4 lezioni in totale.

Cosa imparerò in «API Gateway e individuazione dei servizi»?

Instradi, aggreghi e individui dinamicamente i servizi Eserciti PHP Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare PHP Academy?

Non è richiesta alcuna esperienza precedente. PHP Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «API Gateway e individuazione dei servizi»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione PHP Academy?

Sì. Ogni lezione PHP Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Dal monolite ai microservizi
  2. Comunicazione tra servizi: REST e gRPC
  3. API Gateway e individuazione dei servizi
  4. Resilienza: circuit breaker e retry
← Torna a PHP Academy