OcelotAPI基于.NETCore的网关实现
·
OcelotAPI基于.NETCore的网关实现
1. Ocelot 简介
Ocelot 是一个基于 .NET Core 的开源 API 网关,专为微服务架构设计。它提供以下核心功能:
- 请求路由:将客户端请求映射到后端服务
- 负载均衡:在多个服务实例间分配流量
- 服务聚合:组合多个后端服务的响应
- 认证授权:在网关层实现统一安全控制
- 熔断限流:保护后端服务免受流量冲击
2. 项目结构
Microservices/
├── ValuesService/ # 微服务1 - 提供基础数据
│ ├── Controllers/
│ │ └── ValuesController.cs
│ └── Program.cs
│
├── ProductService/ # 微服务2 - 提供产品数据
│ ├── Controllers/
│ │ └── ProductsController.cs
│ └── Program.cs
│
├── OcelotGateway/ # API网关
│ ├── ocelot.json # 路由配置
│ ├── Program.cs
│ └── Startup.cs # 服务配置
│
└── AuthServer/ # 授权服务器
├── Config.cs # 身份配置
└── Startup.cs
3. 微服务实现
3.1 ValuesService 微服务
ValuesController.cs
[ApiController]
[Route("api/[controller]")]
public class ValuesController : ControllerBase
{
// 返回简单字符串数组
[HttpGet]
public IEnumerable<string> Get()
{
var port = HttpContext.Request.Host.Port;
return new string[] {
$"Value1 (from {port})",
$"Value2 (from {port})",
$"Value3 (from {port})"
};
}
}
启动命令:
dotnet run --urls "http://localhost:5001"
dotnet run --urls "http://localhost:5003" # 第二个实例
3.2 ProductService 微服务
ProductsController.cs
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
// 返回产品列表
[HttpGet]
public IEnumerable<Product> Get()
{
return new List<Product>
{
new Product(1, "Laptop", 999.99),
new Product(2, "Smartphone", 699.99),
new Product(3, "Tablet", 399.99)
};
}
public record Product(int Id, string Name, double Price);
}
启动命令:
bash
dotnet run --urls "http://localhost:5002"
4. API 网关实现
4.1 ocelot.json 配置文件详解
{
"Routes": [
{
// ValuesService 路由配置
"DownstreamPathTemplate": "/api/values", // 后端服务实际路径
"DownstreamScheme": "http", // 后端服务协议
"DownstreamHostAndPorts": [ // 后端服务实例列表
{ "Host": "localhost", "Port": 5001 }, // 实例1
{ "Host": "localhost", "Port": 5003 } // 实例2
],
"UpstreamPathTemplate": "/gateway/values", // 网关暴露路径
"UpstreamHttpMethod": [ "Get" ], // 允许的HTTP方法
"LoadBalancerOptions": { // 负载均衡配置
"Type": "RoundRobin" // 轮询策略
},
"AuthenticationOptions": { // 认证配置
"AuthenticationProviderKey": "Bearer", // 认证方案名称
"AllowAnonymous": false // 禁止匿名访问
},
"RateLimitOptions": { // 限流配置
"EnableRateLimiting": true,
"Period": "1s", // 时间窗口
"Limit": 5 // 请求上限
}
},
{
// ProductService 路由配置
"DownstreamPathTemplate": "/api/products",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{ "Host": "localhost", "Port": 5002 }
],
"UpstreamPathTemplate": "/gateway/products",
"UpstreamHttpMethod": [ "Get" ],
"AuthenticationOptions": {
"AuthenticationProviderKey": "Bearer",
"AllowAnonymous": false
}
}
],
"GlobalConfiguration": {
"BaseUrl": "http://localhost:5000", // 网关基础URL
"RequestIdKey": "OcelotRequestId" // 请求ID标识
}
}
4.2 Startup.cs 配置详解
public void ConfigureServices(IServiceCollection services)
{
// 添加Ocelot服务(自动加载ocelot.json)
services.AddOcelot()
.AddDelegatingHandler<RequestLoggerHandler>(true); // 自定义日志处理器
// JWT认证配置
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "https://localhost:5004"; // 授权服务器地址
options.Audience = "api_gateway"; // API资源名称
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero // 严格校验过期时间
};
});
// 添加内存缓存(用于限流)
services.AddMemoryCache();
// 添加健康检查
services.AddHealthChecks();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
// 启用跨域
app.UseCors("GatewayPolicy");
// 认证授权中间件
app.UseAuthentication();
app.UseAuthorization();
// 健康检查端点
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});
// Ocelot中间件
app.UseOcelot().Wait();
// 自定义中间件:请求日志记录
app.UseMiddleware<RequestLoggingMiddleware>();
}
4.3 自定义日志处理器
RequestLoggerHandler.cs
public class RequestLoggerHandler : DelegatingHandler
{
private readonly ILogger<RequestLoggerHandler> _logger;
public RequestLoggerHandler(ILogger<RequestLoggerHandler> logger)
{
_logger = logger;
}
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
// 记录请求信息
_logger.LogInformation($"Gateway Request: {request.Method} {request.RequestUri}");
// 继续处理请求
var response = await base.SendAsync(request, cancellationToken);
// 记录响应信息
_logger.LogInformation($"Gateway Response: {(int)response.StatusCode} {response.StatusCode}");
return response;
}
}
5. 授权服务器实现
5.1 Config.cs (AuthServer)
public static class Config
{
// API资源定义
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("api_gateway", "API Gateway")
{
Scopes = { "gateway.fullaccess" }
}
};
}
// 客户端定义
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
// 客户端凭证模式
new Client
{
ClientId = "service_client",
ClientSecrets = { new Secret("service_secret".Sha256()) },
AllowedGrantTypes = GrantTypes.ClientCredentials,
AllowedScopes = { "gateway.fullaccess" }
},
// 密码模式(用于用户登录)
new Client
{
ClientId = "user_client",
ClientSecrets = { new Secret("user_secret".Sha256()) },
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
AllowedScopes = { "gateway.fullaccess" }
}
};
}
}
5.2 Startup.cs (AuthServer)
public void ConfigureServices(IServiceCollection services)
{
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients())
.AddTestUsers(TestUsers.Users); // 添加测试用户
}
public void Configure(IApplicationBuilder app)
{
app.UseIdentityServer();
// 提供发现文档端点
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/.well-known/openid-configuration",
async context =>
{
var disco = await context.RequestServices
.GetRequiredService<IDiscoveryResponseGenerator>()
.GenerateAsync();
await context.Response.WriteAsJsonAsync(disco);
});
});
}
6. 运行与测试
6.1 启动顺序
-
启动授权服务器:
cd AuthServer dotnet run --urls "https://localhost:5004" -
启动微服务:
# ValuesService (两个实例) cd ValuesService dotnet run --urls "http://localhost:5001" dotnet run --urls "http://localhost:5003" # ProductService cd ProductService dotnet run --urls "http://localhost:5002" -
启动网关:
cd OcelotGateway dotnet run --urls "http://localhost:5000"
6.2 测试场景
获取访问令牌
# 使用客户端凭证模式
curl -X POST https://localhost:5004/connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "client_id=service_client&client_secret=service_secret&grant_type=client_credentials&scope=gateway.fullaccess"
通过网关访问服务
# 访问ValuesService(负载均衡)
curl -H "Authorization: Bearer <TOKEN>" http://localhost:5000/gateway/values
# 响应示例(轮询显示不同实例):
# ["Value1 (from 5001)", "Value2 (from 5001)", "Value3 (from 5001)"]
# ["Value1 (from 5003)", "Value2 (from 5003)", "Value3 (from 5003)"]
# 访问ProductService
curl -H "Authorization: Bearer <TOKEN>" http://localhost:5000/gateway/products
# 响应示例:
# [{"id":1,"name":"Laptop","price":999.99}, ...]
测试限流功能
# 快速发送10个请求
for i in {1..10}; do
curl -s -H "Authorization: Bearer <TOKEN>" \
-w "HTTP %{http_code}\n" \
http://localhost:5000/gateway/values -o /dev/null
done
# 预期结果:前5个返回200,后续返回429(Too Many Requests)
7. 高级功能实现
7.1 动态负载均衡
Ocelot 支持多种负载均衡策略:
"LoadBalancerOptions": {
"Type": "LeastConnection" // 最小连接数策略
}
可用选项:
RoundRobin:轮询(默认)LeastConnection:最少连接数CookieStickySessions:会话粘滞NoLoadBalancer:无负载均衡
7.2 服务发现集成
结合 Consul 实现动态服务发现:
"GlobalConfiguration": {
"ServiceDiscoveryProvider": {
"Type": "Consul",
"Host": "localhost",
"Port": 8500,
"Token": "<consul_token>"
}
}
7.3 熔断机制
使用 Polly 实现熔断:
{
"Routes": [
{
// ...其他配置
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, // 允许异常次数
"DurationOfBreak": 30, // 熔断时长(秒)
"TimeoutValue": 5000 // 超时时间(毫秒)
}
}
]
}
7.4 请求聚合
创建聚合器:
public class ValuesProductsAggregator : IDefinedAggregator
{
public async Task<DownstreamResponse> Aggregate(List<HttpContext> responses)
{
var values = await responses[0].Items.DownstreamResponse().Content.ReadAsStringAsync();
var products = await responses[1].Items.DownstreamResponse().Content.ReadAsStringAsync();
var content = new {
Values = JsonConvert.DeserializeObject(values),
Products = JsonConvert.DeserializeObject(products)
};
return new DownstreamResponse(
new StringContent(JsonConvert.SerializeObject(content)),
HttpStatusCode.OK,
new HeaderDictionary(),
"OK");
}
}
配置 ocelot.json:
{
"Routes": [
{
"DownstreamPathTemplate": "/api/values",
"UpstreamPathTemplate": "/values",
"Key": "Values",
"UpstreamHttpMethod": ["Get"]
},
{
"DownstreamPathTemplate": "/api/products",
"UpstreamPathTemplate": "/products",
"Key": "Products",
"UpstreamHttpMethod": ["Get"]
}
],
"Aggregates": [
{
"ReRouteKeys": ["Values", "Products"],
"UpstreamPathTemplate": "/aggregated-data",
"Aggregator": "ValuesProductsAggregator"
}
]
}
8. 最佳实践
- 配置管理
- 使用环境变量区分开发/生产配置
- 将敏感数据存储在 Azure Key Vault 或 HashiCorp Vault
- 启用配置热更新:
AddJsonFile("ocelot.json", optional: false, reloadOnChange: true)
- 安全加固
- 启用 HTTPS 终端
- 使用双向 TLS 认证
- 限制管理端点访问
- 高可用
- 部署多个网关实例
- 使用负载均衡器分发流量
- 实现健康检查端点
- 监控日志
- 集成 Application Insights 或 ELK 栈
- 记录请求/响应日志
- 监控关键指标(请求率、延迟、错误率)
- 性能优化
- 启用响应缓存
- 压缩响应内容
- 优化JSON序列化
9. 总结
通过本指南,您已实现了一个完整的 Ocelot API 网关解决方案:
- 核心路由功能:配置
/gateway/values和/gateway/products路由 - 负载均衡:实现 ValuesService 的轮询负载
- 安全认证:集成 JWT 认证和授权
- 高级特性:实现限流、熔断和请求聚合
- 可观测性:添加日志记录和健康检查
Ocelot 网关为微服务架构提供了统一的入口点,有效解决了服务发现、流量管理、安全控制等核心问题。通过灵活的配置和扩展机制,可以满足各种复杂场景的需求。
更多推荐



所有评论(0)