Condividi tramite


Il modello di gateway API rispetto alla comunicazione diretta da client a microservizio

Suggerimento

Questo contenuto è un estratto dell'eBook, Architettura di microservizi .NET per applicazioni .NET containerizzati, disponibile in documentazione .NET o come PDF scaricabile gratuitamente leggibile offline.

Architettura di Microservizi .NET per Applicazioni .NET Containerizzate miniatura della copertina dell'eBook.

In un'architettura di microservizi, ogni microservizio espone un set di endpoint con granularità fine (in genere). Questo fatto può influire sulla comunicazione da client a microservizio, come illustrato in questa sezione.

Comunicazione da client a microservizio diretta

Un possibile approccio consiste nell'usare un'architettura di comunicazione diretta da client a microservizi. In questo approccio, un'app client può effettuare richieste direttamente ad alcuni microservizi, come illustrato nella figura 4-12.

Diagramma che mostra l'architettura di comunicazione da client a microservizio.

Figura 4-12. Uso di un'architettura di comunicazione da client a microservizio diretta

In questo approccio ogni microservizio ha un endpoint pubblico, a volte con una porta TCP diversa per ogni microservizio. Un esempio di URL per un determinato servizio può essere l'URL seguente in Azure:

http://eshoponcontainers.westus.cloudapp.azure.com:88/

In un ambiente di produzione basato su un cluster, tale URL viene mappato al servizio di bilanciamento del carico usato nel cluster, che a sua volta distribuisce le richieste tra i microservizi. Negli ambienti di produzione, è possibile avere un controller per la distribuzione di applicazioni (ADC) come il gateway applicazione di Azure tra i microservizi e Internet. Questo livello funge da livello trasparente che non solo esegue il bilanciamento del carico, ma protegge i servizi offrendo la terminazione SSL. Questo approccio migliora il carico dei tuoi host trasferendo la terminazione SSL ad alto consumo di CPU e altri compiti di routing al Gateway Applicativo di Azure. In ogni caso, un servizio di bilanciamento del carico e ADC sono trasparenti dal punto di vista dell'architettura di un'applicazione logica.

Un'architettura di comunicazione diretta da client a microservizi può essere sufficiente per un'applicazione basata su microservizi di piccole dimensioni, soprattutto se l'app client è un'applicazione Web lato server come un'app MVC ASP.NET. Tuttavia, quando si creano applicazioni di grandi dimensioni e complesse basate su microservizi (ad esempio, quando si gestiscono decine di tipi di microservizi) e soprattutto quando le app client sono app mobili remote o applicazioni web SPA, tale approccio presenta alcuni problemi.

Quando si sviluppa un'applicazione di grandi dimensioni in base ai microservizi, tenere presenti le domande seguenti:

  • In che modo le app client possono ridurre al minimo il numero di richieste al back-end e ridurre le comunicazioni di chat a più microservizi?

L'interazione con più microservizi per creare una singola schermata dell'interfaccia utente aumenta il numero di andata e ritorno attraverso Internet. Questo approccio aumenta la latenza e la complessità sul lato interfaccia utente. Idealmente, le risposte devono essere aggregate in modo efficiente sul lato server. Questo approccio riduce la latenza, poiché più parti di dati tornano in parallelo e alcune interfacce utente possono mostrare i dati non appena sono pronti.

  • In che modo è possibile gestire problemi trasversali, ad esempio autorizzazione, trasformazioni dei dati e invio di richieste dinamiche?

L'implementazione di preoccupazioni trasversali, come la sicurezza e l'autorizzazione, in ogni microservizio può richiedere un impegno significativo per lo sviluppo. Un possibile approccio consiste nell'avere tali servizi all'interno dell'host Docker o del cluster interno per limitare l'accesso diretto a tali servizi dall'esterno e implementare tali problematiche trasversali in una posizione centralizzata, ad esempio un gateway API.

  • In che modo le app client possono comunicare con i servizi che usano protocolli non compatibili con Internet?

I protocolli usati sul lato server (ad esempio AMQP o protocolli binari) non sono supportati nelle app client. Pertanto, le richieste devono essere eseguite tramite protocolli come HTTP/HTTPS e convertiti negli altri protocolli in un secondo momento. Un approccio man-in-the-middle può aiutare in questa situazione.

  • Come è possibile modellare una facciata appositamente creata per le app per dispositivi mobili?

L'API di più microservizi potrebbe non essere ben progettata per le esigenze di applicazioni client diverse. Ad esempio, le esigenze di un'app per dispositivi mobili potrebbero essere diverse dalle esigenze di un'app Web. Per le app per dispositivi mobili, potrebbe essere necessario ottimizzare ulteriormente in modo che le risposte ai dati possano essere più efficienti. È possibile eseguire questa funzionalità aggregando i dati da più microservizi e restituendo un singolo set di dati e a volte eliminando eventuali dati nella risposta non necessari per l'app per dispositivi mobili. E, naturalmente, è possibile comprimere i dati. Anche in questo caso, una facciata o un'API tra l'app per dispositivi mobili e i microservizi può essere utile per questo scenario.

Perché prendere in considerazione i gateway API anziché la comunicazione diretta da client a microservizio

In un'architettura di microservizi, le app client devono in genere usare le funzionalità di più di un microservizio. Se tale utilizzo viene eseguito direttamente, il client deve gestire più chiamate agli endpoint del microservizio. Cosa accade quando l'applicazione evolve e vengono aggiornati i nuovi microservizi o i microservizi esistenti? Se l'applicazione ha molti microservizi, la gestione di così tanti endpoint dalle app client può essere un incubo. Poiché l'app client sarebbe associata a tali endpoint interni, l'evoluzione dei microservizi in futuro può causare un impatto elevato per le app client.

Pertanto, avere un livello intermedio o un livello di riferimento indiretto (gateway) può essere utile per le applicazioni basate su microservizi. Se non si dispone di gateway API, le app client devono inviare richieste direttamente ai microservizi e che generano problemi, ad esempio i problemi seguenti:

  • Accoppiamento: senza il modello di gateway API, le app client sono associate ai microservizi interni. Le app client devono sapere in che modo le più aree dell'applicazione vengono scomposte in microservizi. Durante l'evoluzione e il refactoring dei microservizi interni, queste azioni influiscono sulla manutenzione perché provocano modifiche significative alle app client, a causa del riferimento diretto ai microservizi interni dalle app client. Le app client devono essere aggiornate frequentemente, rendendo più difficile l'evoluzione della soluzione.

  • Troppi round trip: una singola pagina/schermata nell'app client potrebbe richiedere diverse chiamate a più servizi. Questo approccio può comportare più round trip di rete tra il client e il server, aggiungendo una latenza significativa. L'aggregazione gestita in un livello intermedio potrebbe migliorare le prestazioni e l'esperienza utente per l'app client.

  • Problemi di sicurezza: senza un gateway, tutti i microservizi devono essere esposti al "mondo esterno", rendendo la superficie di attacco più grande rispetto a se si nascondono microservizi interni che non vengono usati direttamente dalle app client. Più piccola è la superficie di attacco, più sicura può essere l'applicazione.

  • Problematiche trasversali: ogni microservizio pubblicato pubblicamente deve gestire problemi come l'autorizzazione e SSL. In molte situazioni, questi problemi possono essere gestiti in un singolo livello in modo che i microservizi interni siano semplificati.

Qual è il modello di gateway API?

Quando si progettano e si creano applicazioni basate su microservizi di grandi dimensioni o complesse con più app client, un approccio ottimale da considerare può essere un gateway API. Questo modello è un servizio che fornisce un punto di ingresso singolo per determinati gruppi di microservizi. È simile al modello Facciata dalla progettazione orientata agli oggetti, ma in questo caso fa parte di un sistema distribuito. Il modello di gateway API è talvolta noto anche come "back-end per front-end" (BFF) perché lo si compila pensando alle esigenze dell'app client.

Pertanto, il gateway API si trova tra le app client e i microservizi. Funge da proxy inverso, indirizzando le richieste dai client ai servizi. Può anche fornire altre funzionalità trasversali, ad esempio l'autenticazione, la terminazione SSL e la cache.

La figura 4-13 mostra come un gateway API personalizzato possa essere integrato in un'architettura semplificata basata su microservizi con pochi microservizi.

Diagramma che mostra un gateway API implementato come servizio personalizzato.

Figura 4-13. Uso di un gateway API implementato come servizio personalizzato

Le app si connettono a un singolo endpoint, il gateway API, configurato per inoltrare le richieste ai singoli microservizi. In questo esempio, il gateway API viene implementato come servizio WebHost core ASP.NET personalizzato in esecuzione come contenitore.

È importante evidenziare che in questo diagramma si usa un singolo servizio gateway API personalizzato rivolto a più app client e diverse. Questo può essere un rischio importante perché il servizio Gateway API cresce e si evolve in base a molti requisiti diversi dalle app client. Alla fine, diventerà sovraccarico a causa delle diverse esigenze e finirà per essere simile a un'applicazione monolitica o a un servizio monolitico. Ecco perché è molto consigliabile suddividere il gateway API in più servizi o più gateway API più piccoli, uno per ogni tipo di fattore di forma dell'app client, ad esempio.

È necessario prestare attenzione quando si implementa il modello di gateway API. In genere non è consigliabile disporre di un singolo gateway API aggregando tutti i microservizi interni dell'applicazione. In caso affermativo, funge da aggregatore monolitico o agente di orchestrazione e viola l'autonomia del microservizio accoppiando tutti i microservizi.

Di conseguenza, i gateway API devono essere separati in base ai limiti aziendali e alle app client e non fungono da singolo aggregatore per tutti i microservizi interni.

Quando si suddivide il livello del gateway API in diversi tipi di gateway API, se l'applicazione dispone di più app client, questo può essere il fattore principale quando si identificano i vari tipi di gateway API, in modo da poter avere un'interfaccia diversa per le esigenze di ciascuna app client. Questo caso è un modello denominato "Back-end per front-end" (BFF) in cui ogni gateway API può fornire un'API diversa personalizzata per ogni tipo di app client, possibilmente anche in base al fattore di forma client implementando codice adattatore specifico che sotto chiama più microservizi interni, come illustrato nell'immagine seguente:

Diagramma che mostra più gateway API personalizzati.

Figura 4-13.1. Uso di più gateway API personalizzati

La figura 4-13.1 mostra i gateway API separati per tipo di client; uno per i client mobili e uno per i client Web. Un'app Web tradizionale si connette a un microservizio MVC che usa il gateway API Web. L'esempio illustra un'architettura semplificata con più gateway API con granularità fine. In questo caso, i limiti identificati per ogni API Gateway sono basati esclusivamente sul modello "Backend per Frontend" (BFF), quindi solo sull'API necessaria per ciascuna app cliente. Tuttavia, nelle applicazioni più grandi è consigliabile proseguire e creare altri gateway API in base ai limiti aziendali come secondo pivot di progettazione.

Funzionalità principali nel modello di gateway API

Un gateway API può offrire più funzionalità. A seconda del prodotto, potrebbe offrire funzionalità più avanzate o più semplici, ma le funzionalità più importanti e fondamentali per qualsiasi gateway API sono i modelli di progettazione seguenti:

Routing del proxy inverso o del gateway di rete. Il gateway API offre un proxy inverso per reindirizzare o instradare le richieste (routing di livello 7, in genere richieste HTTP) agli endpoint dei microservizi interni. Il gateway fornisce un singolo endpoint o UN URL per le app client e quindi esegue il mapping interno delle richieste a un gruppo di microservizi interni. Questa funzionalità di routing consente di separare le app client dai microservizi, ma è anche utile quando si modernizza un'API monolitica sfruttando il gateway API tra l'API monolitica e le app client, quindi è possibile aggiungere nuove API come nuovi microservizi pur utilizzando ancora l'API monolitica legacy fino a quando non sia suddivisa in microservizi in futuro. A causa del gateway API, le app client non noteranno se le API usate vengono implementate come microservizi interni o un'API monolitica e soprattutto, quando si evolve e si effettua il refactoring dell'API monolitica in microservizi, grazie al routing del gateway API, le app client non saranno interessate da alcuna modifica dell'URI.

Per altre informazioni, vedere Modello di routing del gateway.

Richiede l'aggregazione. Come parte del modello di gateway è possibile aggregare più richieste client (in genere richieste HTTP) destinate a più microservizi interni in una singola richiesta client. Questo modello è particolarmente utile quando una pagina/schermata client richiede informazioni da diversi microservizi. Con questo approccio, l'app client invia una singola richiesta al gateway API che invia diverse richieste ai microservizi interni e quindi aggrega i risultati e invia tutto all'app client. Il vantaggio principale e l'obiettivo di questo modello di progettazione è ridurre la comunicazione eccessiva tra le app client e l'API back-end, particolarmente importante per le app remote che si trovano fuori dal centro dati dove risiedono i microservizi, come le app per dispositivi mobili o le richieste provenienti da applicazioni a singola pagina (SPA) in JavaScript nei browser remoti dei client. Per le normali app Web che eseguono le richieste nell'ambiente server (ad esempio un'app Web MVC core ASP.NET), questo modello non è così importante perché la latenza è molto più piccola rispetto alle app client remote.

A seconda del prodotto Gateway API usato, potrebbe essere possibile eseguire questa aggregazione. Tuttavia, in molti casi è più flessibile creare microservizi di aggregazione nell'ambito del gateway API, in modo da definire l'aggregazione nel codice ( ovvero codice C#):

Per altre informazioni, vedere Modello di aggregazione del gateway.

Aspetti trasversali o scarico del gateway. A seconda delle funzionalità offerte da ogni prodotto Gateway API, è possibile eseguire l'offload delle funzionalità dai singoli microservizi al gateway, semplificando l'implementazione di ogni microservizio consolidando le problematiche trasversali in un unico livello. Questo approccio è particolarmente utile per le funzionalità specializzate che possono essere complesse da implementare correttamente in ogni microservizio interno, ad esempio le funzionalità seguenti:

  • Autenticazione e autorizzazione
  • Integrazione dell'individuazione dei servizi
  • Memorizzazione nella cache delle risposte
  • Criteri di ripetizione dei tentativi, interruttore e QoS
  • Controllo della velocità e riduzione della velocità
  • Bilanciamento del carico
  • Registrazione, traccia, correlazione
  • Intestazioni, stringhe di interrogazione e trasformazione delle attestazioni
  • Elenco IP autorizzati

Per altre informazioni, vedere Modello di offload del gateway.

Uso di prodotti con funzionalità del gateway API

Esistono molti altri problemi trasversali offerti dai prodotti Gateway API a seconda di ogni implementazione. Esploreremo qui:

Gestione API di Azure

Gestione API di Azure (come illustrato nella figura 4-14) non solo risolve le esigenze del gateway API, ma offre funzionalità come la raccolta di informazioni dettagliate dalle API. Se si usa una soluzione di gestione API, un gateway API è solo un componente all'interno di tale soluzione di gestione API completa.

Diagramma che illustra come usare Gestione API di Azure come gateway API.

Figura 4-14. Uso di Gestione API di Azure per il gateway API

Gestione API di Azure risolve le esigenze di gestione e gateway API, ad esempio registrazione, sicurezza, misurazione e così via. In questo caso, quando si usa un prodotto come Gestione API di Azure, il fatto che potrebbe essere presente un singolo gateway API non è così rischioso perché questi tipi di gateway API sono "più sottili", ovvero non si implementa codice C# personalizzato che potrebbe evolvere verso un componente monolitico.

I prodotti gateway API in genere funzionano come un proxy inverso per la comunicazione in ingresso, in cui è anche possibile filtrare le API dai microservizi interni e applicare l'autorizzazione alle API pubblicate in questo singolo livello.

Le informazioni dettagliate disponibili da un sistema di Gestione API consentono di comprendere il modo in cui vengono usate le API e le prestazioni. Eseguono questa attività consentendo di visualizzare report di analisi quasi in tempo reale e di identificare le tendenze che potrebbero influire sull'azienda. Inoltre, è possibile avere log sull'attività di richiesta e risposta per ulteriori analisi online e offline.

Con Gestione API di Azure è possibile proteggere le API usando una chiave, un token e un filtro IP. Queste funzionalità consentono di applicare quote e limiti di velocità flessibili e granulari, modificare la forma e il comportamento delle API usando i criteri e migliorare le prestazioni con la memorizzazione nella cache delle risposte.

In questa guida e nell'applicazione di esempio di riferimento (eShopOnContainers), l'architettura è limitata a un'architettura in contenitori semplificata e personalizzata per concentrarsi su contenitori semplici senza usare prodotti PaaS come Gestione API di Azure. Tuttavia, per le applicazioni basate su microservizi di grandi dimensioni distribuite in Microsoft Azure, è consigliabile valutare Gestione API di Azure come base per i gateway API nell'ambiente di produzione.

Gattopardo

Ocelot è un gateway API leggero, consigliato per approcci più semplici. Ocelot è un gateway API basato su .NET Core open source appositamente creato per le architetture di microservizi che necessitano di punti di ingresso unificati nei propri sistemi. È leggero, veloce e scalabile e offre routing e autenticazione tra molte altre funzionalità.

Il motivo principale per cui scegliere Ocelot per l'applicazione di riferimento eShopOnContainers 2.0 è dovuto al fatto che Ocelot è un gateway API leggero .NET Core che è possibile distribuire nello stesso ambiente di distribuzione delle applicazioni in cui si distribuiscono i microservizi/contenitori, ad esempio un host Docker, Kubernetes e così via. Poiché si basa su .NET Core, è multipiattaforma che consente di eseguire la distribuzione in Linux o Windows.

I diagrammi precedenti che mostrano gateway API personalizzati in esecuzione nei contenitori sono esattamente come è possibile eseguire Ocelot in un contenitore e in un'applicazione basata su microservizi.

Inoltre, nel mercato sono disponibili molti altri prodotti che offrono funzionalità di Gateway API, ad esempio Apigee, Kong, MuleSoft, WSO2 e altri prodotti come Linkerd e Istio per le funzionalità del controller di ingresso mesh di servizi.

Dopo le sezioni iniziali di spiegazione dell'architettura e dei modelli, le sezioni successive illustrano come implementare i gateway API con Ocelot.

Svantaggi del modello di gateway API

  • L'inconveniente più importante è che quando si implementa un gateway API, si accoppia tale livello con i microservizi interni. L'accoppiamento simile a questo potrebbe causare gravi difficoltà per l'applicazione. Clemens Vaster, architetto del team del bus di servizio di Azure, si riferisce a questa potenziale difficoltà come "il nuovo ESB" nella sessione "Messaging and Microservices" in GOTO 2016.

  • L'uso di un gateway API di microservizi crea un singolo punto di errore aggiuntivo.

  • Un gateway API può introdurre tempi di risposta maggiori a causa della chiamata di rete aggiuntiva. Tuttavia, questa chiamata aggiuntiva in genere ha un impatto minore rispetto alla presenza di un'interfaccia client troppo chatty che chiama direttamente i microservizi interni.

  • Se non è stato eseguito correttamente il ridimensionamento, il gateway API può diventare un collo di bottiglia.

  • Un gateway API richiede costi di sviluppo aggiuntivi e manutenzione futura se include logica personalizzata e aggregazione di dati. Gli sviluppatori devono aggiornare il gateway API per esporre gli endpoint di ogni microservizio. Inoltre, le modifiche all'implementazione nei microservizi interni potrebbero causare modifiche al codice a livello di gateway API. Tuttavia, se il gateway API applica solo sicurezza, registrazione e controllo delle versioni (come quando si usa Gestione API di Azure), questo costo aggiuntivo per lo sviluppo potrebbe non essere applicato.

  • Se il gateway API viene sviluppato da un singolo team, può verificarsi un collo di bottiglia nello sviluppo. Questo aspetto è un altro motivo per cui un approccio migliore consiste nell'avere diversi gateway API con granularità fine che rispondono a esigenze client diverse. È anche possibile separare internamente il gateway API in più aree o livelli di proprietà dei diversi team che lavorano sui microservizi interni.

Risorse aggiuntive