Comprendere il modello API Gateway nei microservizi: una guida semplice

Comprendere il modello API Gateway nei microservizi: una guida semplice

La transizione da un’unica applicazione monolitica a un’architettura a microservizi risolve molti problemi. Consente ai team di lavorare in modo indipendente, distribuire i servizi separatamente e ridimensionare parti del sistema in base alle esigenze. Tuttavia, introduce anche una nuova sfida: come interagiscono i clienti con tutti questi servizi indipendenti?

Se disponi di dieci, cinquanta o centinaia di piccoli microservizi, un’app mobile o una pagina Web dovrebbero connettersi direttamente a ciascuno di essi?

È qui che entra in gioco l’API Gateway Pattern. In questa guida analizzeremo cos’è un API Gateway, perché ne hai bisogno e come semplifica il tuo sistema di microservizi utilizzando parole semplici e analogie con il mondo reale.


L’analogia con il mondo reale: la receptionist dell’hotel

Immagina di soggiornare in un grande hotel resort di lusso. Il resort ha molti dipartimenti diversi:

  • Pulizie (per lenzuola pulite)
  • Servizio in camera (per il cibo) *Concierge (per prenotazione tour)
  • Fatturazione (per pagare la fattura)

Se vuoi un asciugamano pulito, non attraversi il resort cercando di trovare l’edificio delle pulizie. Se vuoi cenare, non bussare alla porta della cucina. Invece, chiami l’addetto alla reception.

L’addetto alla reception ascolta la tua richiesta, determina quale dipartimento può risolverla e ti mette in contatto o la gestisce per te.

In questo scenario:

  • Tu sei il Cliente (App mobile o Browser).
  • L’addetto alla reception è il API Gateway.
  • I dipartimenti (Pulizia, Servizio in camera, Fatturazione) sono i Microservizi.

Il problema: comunicazione diretta dal cliente al servizio

Prima di vedere come funziona il gateway, vediamo cosa succede se non ne usiamo uno.

Supponiamo che la tua applicazione di e-commerce abbia tre microservizi separati:

  1. Servizio utente (gestisce i profili)
  2. Servizio prodotto (gestisce il catalogo)
  3. Servizio ordini (gestisce il pagamento)

Senza un gateway API, l’app client deve inviare richieste separate direttamente all’indirizzo individuale di ciascun servizio (IP o URL):

Diagramma dell'architettura del gateway API che mostra routing, sicurezza e microservizi

Questo approccio di connessione diretta crea diversi grossi grattacapi:

  • Troppi endpoint: l’app client deve ricordare tre URL separati. Se dividi un servizio o ne modifichi l’indirizzo, devi aggiornare l’applicazione client.
  • Security Nightmare: ogni microservizio deve implementare separatamente l’autenticazione (controllo dei token di accesso), i certificati SSL e le regole del firewall.
  • Carico di rete: il cliente potrebbe dover effettuare tre richieste di rete separate su reti mobili lente solo per caricare una singola pagina (ad esempio, recupero del profilo, recupero dei dettagli del prodotto e recupero della cronologia degli ordini).
  • Differenze di protocollo: la tua app client potrebbe preferire l’utilizzo di protocolli Web standard come HTTP/JSON, ma i tuoi servizi interni potrebbero comunicare più velocemente utilizzando protocolli specializzati come gRPC o AMQP.

La soluzione: il modello API Gateway

Un API Gateway è un server di supporto che si trova tra le applicazioni client e i microservizi interni. Funziona come unico punto di ingresso per tutte le richieste in arrivo.

Invece di chiamare tre servizi diversi, il client effettua una chiamata al gateway API. Il gateway inoltra quindi la richiesta al servizio interno corretto, raccoglie i risultati e li invia al client.

Responsabilità chiave di un gateway API

Un gateway API fa molto di più che semplicemente dirigere il traffico. Si prende cura delle “preoccupazioni trasversali”, ovvero attività per le quali ogni microservizio dovrebbe altrimenti scrivere codice:

  1. Routing: il gateway accetta un URL in entrata (come /api/v1/orders) e lo mappa all’indirizzo del servizio interno corretto.
  2. Autenticazione e autorizzazione: il gateway convalida i token di sicurezza (come i JWT) alla porta d’ingresso. Se la richiesta non è valida, viene rifiutata immediatamente, evitando ai tuoi microservizi di sprecare cicli di CPU su richieste non autenticate.
  3. Limitazione della velocità: impedisce a bot dannosi o client difettosi di inviare spam al sistema limitando il numero di richieste che un utente può effettuare al minuto.
  4. Bilanciamento del carico: il gateway può distribuire il traffico in entrata in modo uniforme su più istanze di un microservizio per evitare il sovraccarico di ogni singolo server.
  5. Traduzione del protocollo: può tradurre le richieste JSON rivolte agli utenti in messaggi gRPC interni ad alte prestazioni, consentendo ai servizi di comunicare tra loro nelle loro lingue preferite.

Una semplice implementazione: esempio di codice

Per vedere quanto diventa semplice il routing, esaminiamo due modi comuni per configurare un gateway API.

1. Routing dichiarativo (Spring Cloud Gateway YAML)

Nei sistemi Java aziendali, spesso si configura il routing utilizzando un semplice file di configurazione. Il gateway inoltra automaticamente le richieste in base a queste regole:

spring:
  cloud:
    gateway:
      routes:
        - id: user_service_route
          uri: http://internal-user-service:8081
          predicates:
            - Path=/api/users/**
        - id: product_service_route
          uri: http://internal-product-service:8082
          predicates:
            - Path=/api/products/**

2. Routing programmatico (mockup del gateway Node.js)

Se vuoi creare un gateway API leggero in Javascript utilizzando Express, assomiglia a questo:

const express = require('express');
const { createProxyMiddleware } = require('http-proxy-middleware');
const app = express();
const PORT = 3000;

// 1. Simple Security/Authentication Check at the door
const authenticate = (req, res, next) => {
    const token = req.headers['authorization'];
    if (token === 'secret-handshake-token') {
        next(); // Token is valid, proceed
    } else {
        res.status(401).json({ error: 'Unauthorized Access!' });
    }
};

// Apply auth check to all incoming gateway requests
app.use(authenticate);

// 2. Route requests to correct internal microservices
app.use('/api/users', createProxyMiddleware({ target: 'http://localhost:8081', changeOrigin: true }));
app.use('/api/products', createProxyMiddleware({ target: 'http://localhost:8082', changeOrigin: true }));
app.use('/api/orders', createProxyMiddleware({ target: 'http://localhost:8083', changeOrigin: true }));

app.listen(PORT, () => {
    console.log(`API Gateway running smoothly on port ${PORT}`);
});

Pro e contro del modello API Gateway

Come ogni decisione architetturale, l’utilizzo di un API Gateway comporta dei compromessi:

Vantaggio (Pro) Svantaggio (Con)
Interfaccia client semplice: i client devono conoscere solo un nome di dominio. Single Point of Failure: se il gateway non funziona, l’intera applicazione diventa inaccessibile.
Sicurezza centralizzata: implementa controlli di accesso, SSL e CORS in un unico posto. Latenza extra: le richieste richiedono leggermente più tempo perché devono passare attraverso un hop di rete aggiuntivo.
Riduzione della duplicazione del codice: evita di riscrivere il codice di autenticazione e di limitazione della velocità in ogni servizio. Carenze di manutenzione: il gateway deve essere aggiornato ogni volta che i servizi vengono aggiunti, rimossi o suddivisi.

Conclusione

L’API Gateway Pattern è una pietra angolare della moderna architettura dei microservizi. Agendo come un unico punto di ingresso intelligente, protegge le applicazioni client dalla complessità delle configurazioni dei servizi interni. Semplifica il codice lato client, centralizza la sicurezza e gestisce la gestione del traffico in modo efficiente.

Sebbene introduca un salto di rete minore e debba essere configurato con un’elevata disponibilità in produzione, i vantaggi di basi di codice più pulite, più sicure e gestibili lo rendono un modello altamente raccomandato per qualsiasi sistema distribuito in crescita.


Scopri ulteriori approfondimenti sullo sviluppo software e sull’ingegneria backend sul blog di Ghaznix →