Ocelot API 网关
大约 8 分钟约 2462 字
Ocelot API 网关
简介
Ocelot 是 .NET 平台的开源 API 网关,专为微服务架构设计。它将多个微服务的接口统一为一个入口,提供路由转发、负载均衡、认证授权、限流熔断、缓存聚合等功能。客户端只需与网关通信,无需知道后端服务的具体地址。
特点
安装与配置
NuGet 包
dotnet add package Ocelot
dotnet add package Ocelot.Provider.Consul # Consul 服务发现
dotnet add package Ocelot.Provider.Polly # Polly 熔断
dotnet add package Ocelot.Cache.CacheManager # 缓存基本配置
// Program.cs
var builder = WebApplication.CreateBuilder(args);
// 加载 Ocelot 配置文件
builder.Configuration.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);
builder.Services.AddOcelot(builder.Configuration);
// builder.Services.AddOcelot().AddConsul<Polly>().AddPolly(); // 完整配置
var app = builder.Build();
// 注册 Ocelot 中间件
await app.UseOcelot();
app.Run();路由配置文件
// ocelot.json
{
"Routes": [
{
// 用户服务路由
"UpstreamPathTemplate": "/api/user/{everything}",
"UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ],
"DownstreamPathTemplate": "/api/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{ "Host": "localhost", "Port": 5001 }
],
"UseServiceDiscovery": false
},
{
// 订单服务路由
"UpstreamPathTemplate": "/api/order/{everything}",
"UpstreamHttpMethod": [ "Get", "Post" ],
"DownstreamPathTemplate": "/api/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{ "Host": "localhost", "Port": 5002 }
]
},
{
// 商品服务路由 — 带负载均衡
"UpstreamPathTemplate": "/api/product/{everything}",
"UpstreamHttpMethod": [ "Get" ],
"DownstreamPathTemplate": "/api/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{ "Host": "localhost", "Port": 5003 },
{ "Host": "localhost", "Port": 5004 },
{ "Host": "localhost", "Port": 5005 }
],
"LoadBalancerOptions": {
"Type": "RoundRobin"
}
}
],
"GlobalConfiguration": {
"BaseUrl": "https://localhost:5000"
}
}负载均衡
{
"LoadBalancerOptions": {
"Type": "RoundRobin"
}
}| 策略 | 说明 |
|---|---|
| RoundRobin | 轮询 — 依次分配 |
| LeastConnection | 最少连接 — 分配给连接数最少的服务 |
| NoLoadBalancer | 不做负载均衡 — 使用第一个地址 |
| CookieStickySessions | 基于Cookie的会话保持 |
Consul 服务发现集成
// ocelot.json — 启用服务发现
{
"Routes": [
{
"UpstreamPathTemplate": "/api/user/{everything}",
"UpstreamHttpMethod": [ "Get" ],
"DownstreamPathTemplate": "/api/{everything}",
"DownstreamScheme": "http",
"ServiceName": "user-service",
"UseServiceDiscovery": true,
"LoadBalancerOptions": {
"Type": "RoundRobin"
}
}
],
"GlobalConfiguration": {
"ServiceDiscoveryProvider": {
"Host": "localhost",
"Port": 8500,
"Type": "Consul"
}
}
}// Program.cs — 注册 Consul
builder.Services.AddOcelot(builder.Configuration)
.AddConsul();限流
{
"UpstreamPathTemplate": "/api/order/{everything}",
"UpstreamHttpMethod": [ "Post" ],
"DownstreamPathTemplate": "/api/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{ "Host": "localhost", "Port": 5002 }
],
"RateLimitOptions": {
"ClientWhitelist": [ "admin-client-id" ],
"EnableRateLimiting": true,
"Period": "1m",
"PeriodTimespan": 60,
"Limit": 100
}
}| 配置项 | 说明 |
|---|---|
| Period | 限流周期(1s/1m/1h/1d) |
| Limit | 周期内最大请求数 |
| ClientWhitelist | 白名单(不受限流影响) |
| PeriodTimespan | 超限后重试等待秒数 |
缓存
{
"UpstreamPathTemplate": "/api/product/{everything}",
"UpstreamHttpMethod": [ "Get" ],
"DownstreamPathTemplate": "/api/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{ "Host": "localhost", "Port": 5003 }
],
"FileCacheOptions": {
"TtlSeconds": 60,
"Region": "product-cache"
}
}// Program.cs
builder.Services.AddOcelot(builder.Configuration)
.AddCacheManager(x => x.WithDictionaryHandle());认证集成
{
"UpstreamPathTemplate": "/api/admin/{everything}",
"UpstreamHttpMethod": [ "Get", "Post", "Put", "Delete" ],
"DownstreamPathTemplate": "/api/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{ "Host": "localhost", "Port": 5006 }
],
"AuthenticationOptions": {
"AuthenticationProviderKey": "Bearer",
"AllowedScopes": [ "admin" ]
}
}// Program.cs — 注册 JWT 认证
builder.Services.AddAuthentication()
.AddJwtBearer("Bearer", options =>
{
options.Authority = "https://localhost:5000";
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false
};
});请求聚合
{
"Routes": [
{
"UpstreamPathTemplate": "/api/user/{userId}",
"UpstreamHttpMethod": [ "Get" ],
"DownstreamPathTemplate": "/api/user/{userId}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 5001 } ],
"Key": "User"
},
{
"UpstreamPathTemplate": "/api/order/{userId}",
"UpstreamHttpMethod": [ "Get" ],
"DownstreamPathTemplate": "/api/order/user/{userId}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 5002 } ],
"Key": "Orders"
}
],
"Aggregates": [
{
"RouteKeys": [ "User", "Orders" ],
"UpstreamPathTemplate": "/api/user-order/{userId}",
"UpstreamHttpMethod": [ "Get" ]
}
]
}请求/响应转换
{
"UpstreamPathTemplate": "/api/legacy/{everything}",
"DownstreamPathTemplate": "/api/v2/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [ { "Host": "localhost", "Port": 5001 } ],
"UpstreamHeaderTransform": {
"X-Correlation-Id": "{TraceId}",
"Authorization": "Bearer {RemoteHeaderValue}"
},
"DownstreamHeaderTransform": {
"X-Powered-By": "Ocelot"
}
}熔断与重试
Polly 熔断集成
// ocelot.json — 熔断配置
{
"Routes": [
{
"UpstreamPathTemplate": "/api/order/{everything}",
"UpstreamHttpMethod": [ "Get", "Post" ],
"DownstreamPathTemplate": "/api/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{ "Host": "localhost", "Port": 5002 }
],
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 5000,
"TimeoutValue": 3000
}
}
]
}// Program.cs — 注册 Polly 提供者
builder.Services.AddOcelot(builder.Configuration)
.AddPolly();高级熔断策略
// 自定义 Polly 策略(比配置文件更灵活)
public class CustomPollyRegistry : IPollyQoSResiliencePipelineProvider
{
private readonly ResiliencePipeline<HttpResponseMessage> _pipeline;
public CustomPollyRegistry()
{
_pipeline = new ResiliencePipelineBuilder<HttpResponseMessage>()
.AddRetry(new RetryStrategyOptions<HttpResponseMessage>
{
MaxRetryAttempts = 3,
Delay = TimeSpan.FromMilliseconds(200),
BackoffType = DelayBackoffType.Exponential,
ShouldHandle = new PredicateBuilder<HttpResponseMessage>()
.Handle<HttpRequestException>()
.HandleResult(r => (int)r.StatusCode >= 500)
})
.AddCircuitBreaker(new CircuitBreakerStrategyOptions<HttpResponseMessage>
{
FailureRatio = 0.5,
SamplingDuration = TimeSpan.FromSeconds(30),
MinimumThroughput = 5,
BreakDuration = TimeSpan.FromSeconds(10)
})
.AddTimeout(new TimeoutStrategyOptions
{
Timeout = TimeSpan.FromSeconds(5)
})
.Build();
}
public ResiliencePipeline<HttpResponseMessage> GetQosPipeline(
Route route, DownstreamRoute downstreamRoute)
{
return _pipeline;
}
}
// 注册自定义策略
builder.Services.AddSingleton<IPollyQoSResiliencePipelineProvider, CustomPollyRegistry>();动态路由与配置管理
配置存储在数据库
// 将路由配置存储在数据库,动态刷新
public class DatabaseRouteRepository
{
private readonly IDbConnection _db;
public DatabaseRouteRepository(IDbConnection db) => _db = db;
public async Task<string> GetRoutesAsync()
{
var routes = await _db.QueryAsync<RouteConfig>(
"SELECT * FROM GatewayRoutes WHERE IsActive = 1");
return JsonSerializer.Serialize(new { Routes = routes });
}
}
// 自定义配置提供者
public class DatabaseOcelotConfigurationProvider : FileConfigurationProvider
{
public DatabaseOcelotConfigurationProvider(
DatabaseOcelotConfigurationSource source) : base(source) { }
public override void Load()
{
// 从数据库加载配置
// Data = new DatabaseRouteRepository().GetRoutesAsync().GetAwaiter().GetResult();
}
}
// 替换默认配置源
builder.Services.AddSingleton<IFileConfigurationProvider, DatabaseOcelotConfigurationProvider>();配置热更新
// ocelot.json 中启用 reloadOnChange
// Program.cs 中配置:
// builder.Configuration.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);
// 或者通过 API 动态刷新(Ocelot.Administration)
// 安装:Ocelot.Administration// 启用管理 API
builder.Services.AddOcelot(builder.Configuration)
.AddAdministration("/administration", "secret"); // 路径和密钥
// 管理端点:
// GET /administration/configuration — 获取当前配置
// POST /administration/configuration — 更新配置
// POST /administration/configuration/reroute — 添加路由
// DELETE /administration/configuration/reroute/{id} — 删除路由安全与认证
多种认证方式
// ocelot.json — 多认证提供者
{
"Routes": [
{
"UpstreamPathTemplate": "/api/external/{everything}",
"DownstreamPathTemplate": "/api/{everything}",
"DownstreamScheme": "https",
"DownstreamHostAndPorts": [
{ "Host": "external-api.example.com", "Port": 443 }
],
"AuthenticationOptions": {
"AuthenticationProviderKey": "IdentityServer",
"AllowedScopes": [ "api.read", "api.write" ]
},
"RouteClaimsRequirement": {
"Role": "Admin"
}
}
]
}// Program.cs — 配置 IdentityServer 认证
builder.Services.AddAuthentication()
.AddJwtBearer("IdentityServer", options =>
{
options.Authority = "https://identity.example.com";
options.Audience = "api-gateway";
options.RequireHttpsMetadata = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ClockSkew = TimeSpan.FromMinutes(5)
};
});授权策略
// ocelot.json — 基于声明的授权
{
"RouteClaimsRequirement": {
"Role": "Admin",
"Subscription": "Premium"
}
}// Program.cs — 自定义授权中间件
app.Use(async (context, next) =>
{
// 在 Ocelot 处理之前进行自定义授权
if (context.Request.Path.StartsWithSegments("/api/admin"))
{
var role = context.User.FindFirst("Role")?.Value;
if (role != "SuperAdmin")
{
context.Response.StatusCode = 403;
return;
}
}
await next();
});请求头转换与重写
头部转换
// ocelot.json — 请求/响应头转换
{
"Routes": [
{
"UpstreamPathTemplate": "/api/service/{everything}",
"DownstreamPathTemplate": "/api/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{ "Host": "localhost", "Port": 5001 }
],
"UpstreamHeaderTransform": {
"X-Correlation-Id": "{TraceId}",
"Authorization": "Bearer {RemoteHeaderValue}",
"X-Forwarded-For": "{RemoteIpAddress}",
"X-Real-IP": "{RemoteIpAddress}"
},
"DownstreamHeaderTransform": {
"X-Powered-By": "Ocelot",
"Server": "MyGateway/1.0",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains"
},
"RemoveDownstreamHeaders": [ "X-Powered-By", "Server" ]
}
]
}路径重写
// 旧版本 API 兼容
{
"UpstreamPathTemplate": "/api/v1/users/{id}",
"UpstreamHttpMethod": [ "Get" ],
"DownstreamPathTemplate": "/api/users/{id}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{ "Host": "localhost", "Port": 5001 }
]
}
// 路径参数映射
{
"UpstreamPathTemplate": "/api/orders/{orderId}/items/{itemId}",
"DownstreamPathTemplate": "/api/v2/order-items?orderId={orderId}&itemId={itemId}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{ "Host": "localhost", "Port": 5002 }
]
}日志与可观测性
结构化日志
// Program.cs — 配置 Ocelot 日志
builder.Logging.AddFilter("Ocelot", LogLevel.Information);
builder.Logging.AddFilter("Ocelot.Responder.Middleware", LogLevel.Warning);
// 自定义 Ocelot 日志中间件
public class OcelotLoggingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<OcelotLoggingMiddleware> _logger;
public OcelotLoggingMiddleware(RequestDelegate next, ILogger<OcelotLoggingMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
var correlationId = Guid.NewGuid().ToString("N")[..8];
var sw = Stopwatch.StartNew();
_logger.LogInformation(
"[{CorrelationId}] → {Method} {Path} {QueryString}",
correlationId, context.Request.Method, context.Request.Path,
context.Request.QueryString);
await _next(context);
sw.Stop();
_logger.LogInformation(
"[{CorrelationId}] ← {StatusCode} ({ElapsedMs}ms)",
correlationId, context.Response.StatusCode,
sw.ElapsedMilliseconds);
}
}链路追踪集成
// OpenTelemetry 集成
builder.Services.AddOpenTelemetry()
.WithTracing(tracing =>
{
tracing
.AddSource("Ocelot")
.AddHttpClientInstrumentation()
.AddAspNetCoreInstrumentation()
.AddOtlpExporter(options =>
{
options.Endpoint = new Uri("http://localhost:4317");
});
});高可用部署
多实例部署
# Docker Compose 多实例部署
# docker-compose.yml
# version: '3.8'
# services:
# gateway:
# image: ocelot-gateway:latest
# deploy:
# replicas: 3
# ports:
# - "5000:80"
# depends_on:
# - consul
# consul:
# image: consul:latest
# ports:
# - "8500:8500"// 健康检查配置
builder.Services.AddHealthChecks()
.AddUrlGroup(new Uri("http://localhost:5002/health"), "order-service")
.AddUrlGroup(new Uri("http://localhost:5003/health"), "product-service");
app.MapHealthChecks("/health");蓝绿部署与灰度发布
// 基于权重的路由(Ocelot 16+)
{
"Routes": [
{
"UpstreamPathTemplate": "/api/user/{everything}",
"UpstreamHttpMethod": [ "Get" ],
"DownstreamPathTemplate": "/api/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{ "Host": "user-v1.example.com", "Port": 80 },
{ "Host": "user-v2.example.com", "Port": 80 }
],
"LoadBalancerOptions": {
"Type": "RoundRobin"
}
}
]
}优点
缺点
总结
Ocelot 是 .NET 微服务架构中最常用的 API 网关。如果技术栈全部是 .NET,Ocelot 是最佳选择;如果需要跨语言微服务,可以考虑 Kong 或 Nginx Ingress。
关键知识点
- 先分清这个主题位于请求链路、后台任务链路还是基础设施链路。
- 服务端主题通常不只关心功能正确,还关心稳定性、性能和可观测性。
- 任何框架能力都要结合配置、生命周期、异常传播和外部依赖一起看。
项目落地视角
- 画清请求进入、业务执行、外部调用、日志记录和错误返回的完整路径。
- 为关键链路补齐超时、重试、熔断、追踪和结构化日志。
- 把配置与敏感信息分离,并明确不同环境的差异来源。
常见误区
- 只会堆中间件或组件,不知道它们在链路中的执行顺序。
- 忽略生命周期和线程池、连接池等运行时资源约束。
- 没有监控和测试就对性能或可靠性下结论。
进阶路线
- 继续向运行时行为、可观测性、发布治理和微服务协同深入。
- 把主题和数据库、缓存、消息队列、认证授权联动起来理解。
- 沉淀团队级模板,包括统一异常处理、配置约定和基础设施封装。
适用场景
- 当你准备把《Ocelot API 网关》真正落到项目里时,最适合先在一个独立模块或最小样例里验证关键路径。
- 适合 API 服务、后台任务、实时通信、认证授权和微服务协作场景。
- 当需求开始涉及稳定性、性能、可观测性和发布流程时,这类主题会成为基础设施能力。
落地建议
- 先定义请求链路与失败路径,再决定中间件、过滤器、服务边界和依赖方式。
- 为关键链路补日志、指标、追踪、超时与重试策略。
- 环境配置与敏感信息分离,避免把生产参数写死在代码或镜像里。
排错清单
- 先确认问题发生在路由、模型绑定、中间件、业务层还是基础设施层。
- 检查 DI 生命周期、配置来源、序列化规则和认证上下文。
- 查看线程池、连接池、缓存命中率和外部依赖超时。
复盘问题
- 如果把《Ocelot API 网关》放进你的当前项目,最先要验证的输入、输出和失败路径分别是什么?
- 《Ocelot API 网关》最容易在什么规模、什么边界条件下暴露问题?你会用什么指标或日志去确认?
- 相比默认实现或替代方案,采用《Ocelot API 网关》最大的收益和代价分别是什么?
