immagine di un gateway evocativa delle gateway API

Microservizi in C#: quando usare un API Gateway con Ocelot

I microservizi sono diventati uno standard de-facto per costruire sistemi scalabili e autonomi. In ambito .NET/C#, l’ecosistema offre tooling maturo per deploy containerizzato, osservabilità e integrazioni cloud. In questo articolo vediamo linee guida pratiche e valutiamo pro/contro dell’uso di un API Gateway con Ocelot.

Perché usare i microservizi (e quando evitarli)

Vantaggi

  • Scalabilità indipendente: ogni servizio scala secondo il proprio carico.
  • Autonomia dei team: ownership chiara, rilasci indipendenti.
  • Resilienza: un fault resta confinato al servizio (se ben progettato).
  • Polyglot persistence: ogni servizio sceglie il proprio database.

Svantaggi

  • Distributed complexity: rete, latenza, fallimenti parziali, versioning API.
  • Osservabilità necessaria: logging, tracing e metrics diventano fondamentali.
  • Data consistency: niente ACID cross-service; servono Saga e Outbox Pattern.
  • Costi operativi: più repository, pipeline, infrastruttura.

Regola d’oro: se il dominio è piccolo o il team è ridotto, considera modular monolith con boundaries chiari; migri a microservizi quando la complessità lo giustifica.


Pratiche consigliate in C#

  • Bounded Context (DDD): ogni servizio incapsula il suo modello e il suo DB.
  • Clean Architecture: separa Domain, Application, Infrastructure, Web.
  • Messaging: eventi asincroni con RabbitMQ, Kafka o Azure Service Bus.
  • Data consistency: Outbox + Transactional Inbox, Idempotency.
  • Observability (OpenTelemetry): trace distributed, logs strutturati, metrics.
  • Health checks & readiness: AspNetCore.Diagnostics.HealthChecks.
  • Security: OAuth2/OIDC (IdentityServer, Azure AD), secrets su Key Vault/Secrets Manager.
  • Container & CI/CD: Dockerfile minimal, GitHub Actions/Azure DevOps, canary/blue-green.
  • Test: unit/integration, contract testing (Pact) tra servizi.

Cos’è un API Gateway

In un’architettura a microservizi i client non dovrebbero parlare direttamente con i singoli servizi. L’API Gateway fa da reverse proxy/facciata unica per:

  • Routing e aggregazione di chiamate.
  • AuthN/AuthZ (delegata a un Identity Provider), rate limiting, caching.
  • QoS/Resilience: retry, timeout, circuit breaker.
  • Transformation: riscrittura header/URL, mapping payload.

Alternative comuni: Ocelot (C#), YARP (C#, reverse proxy evoluto), NGINX/Envoy, Kong/Traefik, Azure API Management, AWS API Gateway.


Ocelot in breve

Ocelot è un API Gateway leggero scritto in .NET, configurato via JSON o code-based. Copre routing, aggregation, QoS (via Polly), rate limiting, caching, service discovery (Consul/Eureka), auth delegata con JWT.

Setup rapido

1) Pacchetti

dotnet add package Ocelot
dotnet add package Ocelot.Cache.CacheManager
dotnet add package Ocelot.Provider.Consul
dotnet add package Microsoft.Extensions.Configuration.Json

2) ocelot.json (routing base)

jsonCopiaModifica{
  "Routes": [
    {
      "DownstreamPathTemplate": "/api/orders/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [ { "Host": "orders-svc", "Port": 5000 } ],
      "UpstreamPathTemplate": "/orders/{everything}",
      "UpstreamHttpMethod": [ "GET", "POST", "PUT", "DELETE" ],
      "QoSOptions": { "ExceptionsAllowedBeforeBreaking": 3, "DurationOfBreak": 5, "TimeoutValue": 3000 },
      "RateLimitOptions": { "EnableRateLimiting": true, "Period": "1s", "Limit": 10 }
    }
  ],
  "GlobalConfiguration": {
    "BaseUrl": "https://api.mycompany.com"
  }
}

3) Program.cs (minimal hosting)

csharpCopiaModificausing Ocelot.DependencyInjection;
using Ocelot.Middleware;

var builder = WebApplication.CreateBuilder(args);

// Carica config Ocelot
builder.Configuration.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);

// Ocelot + Cache
builder.Services.AddOcelot()
    .AddCacheManager(x => x.WithDictionaryHandle());

// (Opzionale) Auth JWT
builder.Services.AddAuthentication("Bearer")
    .AddJwtBearer("Bearer", options =>
    {
        options.Authority = "https://identity.mycompany.com";
        options.Audience = "api";
        options.RequireHttpsMetadata = true;
    });

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();

await app.UseOcelot();
app.Run();

Request Aggregation (esempio)

jsonCopiaModifica{
  "Routes": [
    { "DownstreamPathTemplate": "/api/customers/{id}", "UpstreamPathTemplate": "/customers/{id}", "DownstreamHostAndPorts": [{ "Host":"customers-svc","Port":5001 }], "DownstreamScheme":"http" },
    { "DownstreamPathTemplate": "/api/orders/by-customer/{id}", "UpstreamPathTemplate": "/orders/by-customer/{id}", "DownstreamHostAndPorts": [{ "Host":"orders-svc","Port":5002 }], "DownstreamScheme":"http" }
  ],
  "Aggregates": [
    {
      "RouteKeys": [ "/customers/{id}", "/orders/by-customer/{id}" ],
      "UpstreamPathTemplate": "/customer-dashboard/{id}"
    }
  ]
}

Con una sola call /customer-dashboard/{id} il client ottiene customer + ordini.


Pro e contro di un API Gateway con Ocelot

Pro

  • .NET-native: stesso stack dei microservizi, semplicità di deploy (container/K8s).
  • Configurazione semplice: ocelot.json leggibile, reload on change.
  • Feature essenziali: routing, rate limiting, caching, QoS (Polly), aggregation.
  • Service discovery: integrazione con Consul/Eureka; supporto a load balancing downstream.
  • Performance adeguate per la maggior parte degli use case mid-scale.

Contro

  • Scope funzionale più “snello” rispetto a API gateway enterprise (es. Azure API Management, Kong) su: analytics avanzate, developer portal, monetizzazione, policy visuali, versioning contrattuale, mocking.
  • Manutenzione/estendibilità: per scenari spinti (migliaia di route, policy complesse, trasformazioni pesanti), potresti preferire YARP (programmabilità alta) o Envoy/Kong (ecosistema ricco).
  • Observability integrata limitata: va completata con OpenTelemetry, log forwarding e dashboards.
  • Aggregation server-side: utile ma può introdurre colli di bottiglia se abusata; valuta BFF pattern per frontends diversi.

Quando scegliere Ocelot, YARP o un gateway “enterprise”

Scegli Ocelot se:

  • vuoi un gateway semplice, veloce da mettere in piedi, tutto in .NET;
  • servono routing/QoS/rate limit/aggregation senza fronzoli;
  • team .NET, pipeline già pronte, cluster K8s “interno” o self-hosted.

Scegli YARP se:

  • ti serve programmabilità profonda in C# (custom load balancer, trasformazioni complesse);
  • hai moltissime route e vuoi gestirle “as code” con flessibilità massima.

Scegli un gateway gestito/enterprise (Azure APIM, Kong, Tyk) se:

  • necessiti developer portal, productization delle API, analytics, quota/monetization;
  • vuoi policy avanzate, governance centrale e integrazione nativa con servizi cloud.

Performance, resilienza e sicurezza: checklist rapida

  • Timeout & Retry: imposta timeout downstream realistici, retry con jitter; evita retry su operazioni non idempotenti.
  • Circuit Breaker: proteggi il backend e riduci la latenza percepita.
  • Caching: risposte GET idempotenti, invalida in modo mirato.
  • Rate Limiting: limita abuso e spike; coordina con WAF/CDN (Cloudflare/Azure Front Door).
  • mTLS/Zero-Trust (east-west): per traffico interno sensibile.
  • Security headers e JWT validation lato gateway (audience, scopes/roles).
  • Canary/Blue-Green: instrada percentuali diverse verso nuove versioni downstream.
  • Autoscaling: HPA su CPU/RAM/latency; readiness/liveness probes.
  • Observability: distributed tracing (W3C TraceContext), logs strutturati, SLO/alerting.

Esempio di pipeline e deploy (Kubernetes)

  • Build container: docker build -t registry/api-gateway:1.0 .
  • Manifests K8s: Deployment con readinessProbe su /health, ConfigMap per ocelot.json.
  • Secrets per JWT/Keys, risorse (CPU/RAM) definite, HPA attivo.
  • Ingress/LoadBalancer davanti al Gateway; NetworkPolicies per traffico interno.

Conclusioni

I microservizi in C# funzionano al meglio con confini di dominio chiari, messaging asincrono e una solida osservabilità. Un API Gateway è la porta d’ingresso del tuo ecosistema: Ocelot è una scelta pratica e leggera quando vuoi restare full-.NET e coprire le esigenze core (routing, QoS, rate limiting, aggregation). Se invece cerchi governance avanzata, analytics e developer portal, orientati a una soluzione enterprise; se vuoi massima programmabilità in C#, valuta YARP.

Takeaway: parti semplice (Ocelot o YARP), misura e automatizza; quando la complessità organizzativa e di prodotto cresce, fai upgrade del gateway senza stravolgere il design dei tuoi servizi.


Pubblicato

in

da

Tag: