Nel mondo delle architetture moderne, specialmente quelle basate su microservizi, l’API Gateway rappresenta un componente fondamentale per gestire efficacemente la comunicazione tra client e servizi. Con questo articolo vorrei raggiungere due obiettivi: il primo è chiarire quali sono i vantaggi di un api gateway (e quando non serve utilizzarlo) mentre il secondo è di configurare un progetto di esempio.
Cos’è un API Gateway?
Un API Gateway agisce come punto di ingresso unificato per tutte le richieste client in un’architettura a microservizi. Immaginate un portiere in un grande edificio che sa esattamente dove dirigere ogni visitatore: l’API Gateway svolge un ruolo simile per le richieste API, con qualche vantaggio in più.
Aggiungo inoltre che un progetto architetturalmente complesso potrebbe avere più progetti di API gateway. Ipotizziamo di avere un backend comune e diversi frontend per desktop, tablet e app: sarebbe corretto creare un API Gateway per ognuno di questi frontend (approccio Backend for Frontend o BFF).
Perché Abbiamo Bisogno di un API Gateway?
L’utilizzo di un API Gateway diventa cruciale per diversi motivi, vediamoli insieme:
Gestione del Routing Centralizzata: Immaginate di avere un microservizio chiamato “OrderService”, il quale ha più istanze. Ogni istanza ha un indirizzo IP e una porta differente, cosa si dovrebbe fare in tutti gli altri servizi che necessitano di richiamare questo servizio? Dovrebbero conoscere esattamente dove sono tutte le istanze di OrderService. Sfruttando un API gateway centralizziamo questa responsabilità in un punto unico (su questo punto specifico potremmo parlare anche di service discovery ma lo affronteremo in una articolo dedicato).
Monitoraggio e sicurezza L’API Gateway non si occupa solamente di instradare le chiamate ma può gestire – sempre in un punto unico – diversi altri aspetti quali
- Autenticazione e autorizzazione
- Logging centralizzato
- Monitoraggio delle prestazioni
- Rate limiting (per esempio contro attacchi DDoS)
Inoltre il contenuto e l’architettura del sistema (monolitico o a microservizi) è nascosto e l’unico punto per accedere agli endpoint è passare dall’api gateway.
Caching e aggregazione: in un contesto a micro servizi è spesso utile gestire degli endpoint che vadano ad aggregare e trasformare i dati recuperati da diverse fonti dati (es. un endpoint che aggrega le risposte di altri 3 micro servizi). Un altro vantaggio è rappresentato dal fatto che si possono inserire in cache le risposte, inoltrando le chiamate ai servizi solo quando necessario
Load Balancing: un api gateway evoluto (come Ocelot, che vedremo più avanti in questo articolo) è possibile andare a distribuire il carico di chiamate tra più istanze di un servizio. Questo, applicato ad un meccanismo di service discovery, diventa un aspetto fondamentale per rendere performante un’applicazione distribuita in quanto evita di creare colli di bottiglia.
Circuit Breaking: Implementa pattern di resilienza per gestire i fallimenti dei servizi downstream.
API Gateway con Ocelot
Ocelot è una libreria Open Source gratuita molto completa e mantenuta che ci permette di realizzare il nostro api gateway (qui trovate il repository Github e qui la documentazione).
Di default la libreria permette di fare davvero tante cose ed espone anche delle interfacce per poter estendere alcune funzionalità (es. interfaccia IOcelotCache<CachedResponse>
per creare un servizio custom di gestione delle cache).
Ocelot non dispone di una GUI per poterla gestire (anche se è possibile aggiungere swagger per visualizzare gli endpoint configurai) ma ogni configurazione è gestita all’interno di uno o più file .json, dove andremo a definire le rotte e le varie configurazioni.
E’ ora di sporcarci le mani 😈
Vediamo passo a passo come creare una soluzione composta da 3 progetti:
- Ocelot.ApiGateway
- Gateway Ocelot
- Progetto ASP .Net Core Web Api)
- https://localhost:7500
- Ocelot.ProductService
- Primo micro servizio
- Progetto ASP .Net Core Web Api
- https://localhost:7501
- Ocelot.OrderService
- Secondo micro servizio
- Progetto ASP .Net Core Web Api
- https://localhost:7502
Apriamo quindi Visual Studio, creiamo una nuova solution e creiamo i 3 progetti.

Configurazione del servizio ProductService
All’interno del primo servizio andiamo ad aggiungere un nuovo Controller chiamato “ProductsController.cs” (di default vi troverete già con il controller WeatherForecasrController, se volete potete cancellarlo)
Creiamo un semplice controller per i prodotti:
using Microsoft.AspNetCore.Mvc;
namespace ProductService.Controllers;
[ApiController]
[Route("api/v1/[controller]")]
public class ProductsController : ControllerBase
{
private static readonly string[] Products = new[]
{
"Laptop", "Smartphone", "Tablet", "Smartwatch"
};
[HttpGet]
public IActionResult Get()
{
return Ok(Products);
}
}
Configurazione del servizio OrderService
Spostiamoci ora sul secondo servizio, anche in questo caso creiamo un nuovo controller chiamato “OrdersController“
using Microsoft.AspNetCore.Mvc;
namespace OrderService.Controllers;
[ApiController]
[Route("api/v1/[controller]")]
public class OrdersController : ControllerBase
{
private static readonly string[] Orders = new[]
{
"Order-001", "Order-002", "Order-003"
};
[HttpGet]
public IActionResult Get()
{
return Ok(Orders);
}
}
Configurazione dell’API Gateway con Ocelot
Abbiamo configurato i due servizi che rappresenteranno due micro servizi, ora dedichiamoci a configurare Ocelot. Per iniziare installiamo questo pacchetto nel progetto Ocelot.ApiGateway:
dotnet add package Ocelot
Spostiamoci ora nel file Program.cs e aggiungiamo le righe che sono state evidenziate.
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
var builder = WebApplication.CreateBuilder(args);
//Middleware Ocelot
builder.Services.AddOcelot(builder.Configuration);
builder.Configuration.AddJsonFile("ocelot.json");
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.UseHttpsRedirection();
await app.UseOcelot();
app.Run();
Avrete sicuramente notato che abbiamo aggiunto un file “ocelot.json“, aggiungiamolo alla solution allo stesso livello dei file appsettings.json.
Questo è il file che utilizzeremo per definire le rotte di instradamento verso i vari micro servizi. Il file di base si presenta così:
{
"Routes": [ ],
"GlobalConfiguration": {
"BaseUrl": "https://localhost:7500"
}
}
GlobalConfiguration: definisce delle caratteristiche globali, in questo caso abbiamo definito l’endpoint base che ha il progetto Ocelot.ApiGateway
una volta avviato.
Routes: è l’elemento principale della configurazione, definisce la lista delle rotte. Ogni rotta ha questa struttura:
{
"UpstreamHttpMethod": [ "Put", "Delete" ],
"UpstreamPathTemplate": "/posts/{postId}",
"DownstreamPathTemplate": "/api/posts/{postId}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{ "Host": "localhost", "Port": 80 }
]
}
Gli elementi che iniziano con DownStream
definiscono dove andrà instradata la chiamata API (nel nostro caso andremo a definire gli endpoint dei servizi che abbiamo realizzato prima)
Gli elementi che iniziano con UpStream
definiscono invece l’endpoint che Ocelot esporrà.
Compilando questa ultima parte e aggiungendolo al file generale “ocelot.json” ecco che questo è il nostro risultato:
{
"Routes": [
{
"UpstreamPathTemplate": "/api/catalogs/products",
"UpstreamHttpMethod": [ "Get" ],
"DownstreamPathTemplate": "/api/v1/products",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{ "Host": "localhost", "Port": 7502 }
],
},
],
"GlobalConfiguration": {
"BaseUrl": "https://localhost:7500"
}
}
Configurazione delle porte dei servizi
Modifichiamo le porte nei file Properties/launchSettings.json di ciascun progetto, configurando gli endpoint in questo modo:
ApiGateway: porta 7500
ProductService: porta 7501
OrderService: porta 7502
Avvamo il progetto e proviamo il nostro API Gateway (volendo potete configurare i file .http che trovere già inclusi nel progetto, qui c’è la mia guida su come fare). Richiamando gli endpoint presenti sulla porta 7500 le chiamate verranno instradate verso i due servizi, disponibili sulla porta 7501 e 7502.

Conclusioni
L’implementazione di un API Gateway con Ocelot in .NET Core offre numerosi vantaggi:
1. Semplicità di Implementazione:
Ocelot fornisce un’interfaccia chiara e una configurazione basata su JSON che rende semplice iniziare.
2. Flessibilità:
La possibilità di configurare routing, autenticazione e altri aspetti in modo dichiarativo permette di adattare facilmente il gateway alle esigenze specifiche.
3. Scalabilità:
L’architettura permette di aggiungere nuovi servizi senza modificare i client esistenti. I scenari più complessi subentra anche il concetto di service discovery, considerato che i servizi sono numericamente mutabili nel tempo e non sempre hanno un indirizzo fisso. Ocelot supporta tutto questo ma non è stato afforntato in questo articolo per questioni si semplicità
4. Manutenibilità:
La centralizzazione della logica di routing e delle politiche di sicurezza semplifica la gestione dell’infrastruttura.
Tuttavia, è importante considerare che l’introduzione di un API Gateway aggiunge un nuovo livello di complessità all’architettura e potrebbe introdurre un punto singolo di fallimento se non progettato correttamente. È fondamentale valutare attentamente i requisiti del proprio sistema e implementare appropriate strategie di resilienza e scalabilità.