| name | ocelot-gateway-guide |
| description | Configuration d'Ocelot comme API Gateway en .NET — routing, aggregation, rate limiting, load balancing et intégration Consul/Kubernetes. À utiliser quand l'utilisateur implémente une gateway API avec Ocelot en .NET. Se déclenche aussi avec "Ocelot", "Ocelot gateway", "ocelot.json", "API gateway Ocelot", "routing Ocelot", "aggregation Ocelot". Also triggers on ".NET API gateway", "Ocelot routing". |
Guide Ocelot API Gateway
Workflow — mise en place pas à pas
1. Installer les packages
dotnet add package Ocelot
dotnet add package Ocelot.Provider.Consul
dotnet add package Ocelot.Provider.Eureka
dotnet add package Ocelot.Cache.CacheManager
dotnet add package Ocelot.Tracing.OpenTracing
2. Brancher Ocelot dans Program.cs
var builder = WebApplication.CreateBuilder(args);
builder.Configuration
.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true)
.AddJsonFile($"ocelot.{builder.Environment.EnvironmentName}.json",
optional: true, reloadOnChange: true);
builder.Services
.AddOcelot(builder.Configuration)
.AddCacheManager(x => x.WithDictionaryHandle())
.AddConsul()
;
builder.Services.AddAuthentication()
.AddJwtBearer("Bearer", options =>
{
options.Authority = builder.Configuration["Jwt:Authority"];
options.Audience = builder.Configuration["Jwt:Audience"];
});
var app = builder.Build();
await app.UseOcelot();
app.Run();
3. Définir les routes dans ocelot.json
Chaque route = un objet dans "Routes". Minima obligatoires :
{
"Routes": [
{
"DownstreamPathTemplate": "/api/payments/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{ "Host": "payment-service", "Port": 8080 }
],
"UpstreamPathTemplate": "/payments/{everything}",
"UpstreamHttpMethod": ["GET", "POST", "PUT", "DELETE"],
"AuthenticationOptions": {
"AuthenticationProviderKey": "Bearer"
},
"RateLimitOptions": {
"EnableRateLimiting"
4. Aggregation de requêtes
Agrège plusieurs appels downstream en une seule réponse upstream. Utiliser la clé "Key" sur chaque route participante :
{
"Routes": [
{
"DownstreamPathTemplate": "/api/users/{userId}",
"UpstreamPathTemplate": "/users/{userId}",
"DownstreamHostAndPorts": [{ "Host": "user-svc", "Port": 8080 }],
"Key": "user"
},
{
"DownstreamPathTemplate": "/api/orders?userId={userId}",
"UpstreamPathTemplate": "/users/{userId}/orders",
"DownstreamHostAndPorts": [{ "Host": "order-svc", "Port": 8080 }],
"Key"
Limite : l'agrégation ne supporte que GET. Pour des cas complexes (POST, transformation de payload), implémenter un custom IDefinedAggregator.
5. Service Discovery avec Consul
builder.Services.AddOcelot().AddConsul();
{
"Routes": [
{
"DownstreamPathTemplate": "/api/{everything}",
"UpstreamPathTemplate": "/payments/{everything}",
"ServiceName": "payment-service",
"LoadBalancerOptions": { "Type": "LeastConnection" }
}
],
"GlobalConfiguration": {
"ServiceDiscoveryProvider": {
"Scheme": "http",
"Host": "consul",
"Port": 8500,
"Type": "Consul",
"PollingInterval": 5000
}
}
}
6. Headers et claims transformation
{
"AddHeadersToRequest": {
"X-Tenant-Id": "Claims[tenant_id] > value"
},
"AddClaimsToRequest": {
"sub": "Claims[sub] > value"
},
"AddQueriesToRequest": {
"clientId": "Claims[client_id] > value"
},
"UpstreamHeaderTransform": {
"X-Forwarded-For": "{RemoteIpAddress}"
},
"DownstreamHeaderTransform": {
"Location": "{DownstreamBaseUrl}/{UpstreamBaseUrl}"
}
}
7. Middleware personnalisé
app.Use(async (ctx, next) =>
{
ctx.Request.Headers["X-Correlation-Id"] =
ctx.Request.Headers.TryGetValue("X-Correlation-Id", out var existing)
? existing.ToString()
: Guid.NewGuid().ToString("N");
await next();
});
await app.UseOcelot();
Critères de décision — Ocelot vs YARP
| Critère | Ocelot | YARP |
|---|
| Configuration | JSON déclaratif | Code + config |
| Aggregation intégrée | Oui | Non (custom) |
| Service Discovery | Consul, Eureka | Custom |
| Performance | Bonne | Excellente (Microsoft) |
| Maintenance | Communauté | Microsoft officiel |
| Courbe d'apprentissage | Faible | Moyenne |
| Cas d'usage | Équipes petites/moyennes, config déclarative | Proxy haute performance, finops |
Choisir Ocelot si : config JSON suffisante, aggregation native requise, équipe habituée au routing déclaratif.
Choisir YARP si : throughput critique (>50k req/s), besoin de transformations complexes en code.
Garde-fous et anti-patterns
Ne pas faire :
- Laisser une route sans
QoSOptions — un service lent bloque toute la gateway.
- Partager un seul
ocelot.json pour tous les environnements — utiliser ocelot.{env}.json.
- Utiliser le cache (
FileCacheOptions) sur des routes POST/PUT/DELETE — effets de bord silencieux.
- Masquer les erreurs d'aggregation : si un sous-appel échoue, retourner un corps partiel avec un statut
207 Multi-Status et logger chaque sous-requête individuellement.
- Exposer le port Consul admin (
8500) sur le réseau public.
- Stocker les secrets (
Jwt:Authority, clés API) en clair dans ocelot.json — utiliser les variables d'environnement ou un vault.
Pièges courants :
UpstreamPathTemplate trop générique (/{everything}) capte tout et masque d'autres routes. Toujours ordonner du plus spécifique au plus général.
- L'aggregation retourne HTTP 200 même si les sous-requêtes ont échoué — vérifier chaque body de la réponse agrégée.
reloadOnChange: true sur ocelot.json peut causer un reload à chaud en production ; tester en staging d'abord.
- Le circuit breaker (
QoSOptions) nécessite le package Polly — sans lui, les options sont ignorées silencieusement.
Bonnes pratiques 2026
- Versionner
ocelot.json avec le code source, jamais dans un ConfigMap Kubernetes non tracé.
- Activer les health checks Ocelot avec
/health et lier à la readiness probe.
- Utiliser
LeastConnection plutôt que RoundRobin dès que les services ont des latences inégales.
- En Kubernetes, préférer le Service Discovery natif (
Kube) plutôt que Consul sauf si multi-cluster.
- Exposer les métriques via OpenTelemetry (
Ocelot.Tracing.OpenTracing) et les consommer dans Grafana.
- Limiter le nombre de routes par fichier à ~50 ; au-delà, splitter en fichiers partiels chargés via
AddOcelot(builder.Configuration).