在微服务架构里,前端如果直连各个后端服务,不仅会面临接口地址碎片化,还会让鉴权、日志和限流逻辑重复散落。使用C#搭建API网关,可以把所有下游服务的入口收敛到统一域名之下。Ocelot是.NET生态中成熟的开源网关组件,基于ASP.NET Core管道运行,通过JSON配置即可完成路由转发、负载均衡和请求聚合。

一、创建基础网关项目并引入Ocelot
首先使用命令行或Visual Studio建立一个空的ASP.NET Core Web API项目,命名为ApiGateway。Ocelot以NuGet包形式发布,当前主流版本支持.NET 6及以上运行时。安装完成后,不需要编写传统Controller,网关的核心逻辑全部由配置驱动。
在Program.cs中,我们不再使用默认的控制器映射,而是把Ocelot中间件挂到管道中。下面代码展示了最小可用的宿主配置,其中AddOcelot会读取根目录下的ocelot.json文件。
// Program.cs 基础配置
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
var builder = WebApplication.CreateBuilder(args);
// 加载名为 ocelot.json 的配置文件
builder.Configuration.AddJsonFile("ocelot.json", optional: false, reloadOnChange: true);
builder.Services.AddOcelot(builder.Configuration);
var app = builder.Build();
// 使用 Ocelot 中间件处理所有请求
await app.UseOcelot();
app.Run();
上述代码里,AddJsonFile的reloadOnChange设为true,这样修改ocelot.json后网关会自动热加载,不需要重启进程。对于生产环境,建议把配置文件放到配置中心,但通过本地文件快速验证依然是最高效的起步方式。
二、高级路由与下游服务负载均衡
Ocelot的Routes节点定义了上游路径与下游服务的映射关系。高级用法中,我们常为同一组下游服务配置多个实例地址,并指定负载均衡算法。例如对订单服务做轮询,对用户服务做最小连接数分发。
下面配置展示了带负载均衡的路由:当请求网关的 /order/{everything} 时,会被转发到两个订单节点之一。LoadBalancerOptions的Type支持RoundRobin、LeastConnection等。同时可以配置超时和熔断,避免单点慢响应拖垮网关。
{
"Routes": [
{
"DownstreamPathTemplate": "/api/order/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{ "Host": "192.168.0.1", "Port": 5001 },
{ "Host": "192.168.0.1", "Port": 5002 }
],
"UpstreamPathTemplate": "/order/{everything}",
"UpstreamHttpMethod": [ "Get", "Post" ],
"LoadBalancerOptions": {
"Type": "RoundRobin"
},
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3,
"DurationOfBreak": 5000,
"TimeoutValue": 2000
}
}
],
"GlobalConfiguration": {
"BaseUrl": "http://ipipp.com"
}
}
QoSOptions中的DurationOfBreak表示熔断后暂停转发的时间,TimeoutValue是单次请求最大等待毫秒数。这种配置让网关具备了基础的弹性能力,比在每一个微服务里单独接Polly要省心得多。
三、请求聚合与自定义中间件
前端有时需要一次拿到用户信息和订单摘要,如果分别调用两个接口会增加延迟。Ocelot支持用Aggregates把多个路由结果合并返回。此外,在转发前注入自定义中间件,可以统一添加追踪头或剥离内部鉴权信息。
聚合配置需要在Routes里先定义两个子路由,再在Aggregates中引用它们的Key。下面的示例把用户和订单聚合到 /getuserorder 路径。自定义中间件则通过app.UseMiddleware挂载在UseOcelot之前,对进入网关的请求做预处理。
{
"Routes": [
{
"Key": "User",
"DownstreamPathTemplate": "/api/user/{id}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [ { "Host": "127.0.0.1", "Port": 6001 } ],
"UpstreamPathTemplate": "/user/{id}"
},
{
"Key": "Order",
"DownstreamPathTemplate": "/api/order/{id}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [ { "Host": "127.0.0.1", "Port": 6002 } ],
"UpstreamPathTemplate": "/order/{id}"
}
],
"Aggregates": [
{
"RouteKeys": [ "User", "Order"],
"UpstreamPathTemplate": "/getuserorder/{id}"
}
]
}
对应的C#中间件示例,用于在请求头中写入调用链ID:
// TraceMiddleware.cs
using Microsoft.AspNetCore.Http;
using System.Threading.Tasks;
public class TraceMiddleware
{
private readonly RequestDelegate _next;
public TraceMiddleware(RequestDelegate next) { _next = next; }
public async Task InvokeAsync(HttpContext context)
{
if (!context.Request.Headers.ContainsKey("X-Trace-Id"))
{
context.Request.Headers["X-Trace-Id"] = System.Guid.NewGuid().ToString();
}
await _next(context);
}
}
// Program.cs 中注册
// app.UseMiddleware<TraceMiddleware>();
// await app.UseOcelot();
聚合返回结构是各子路由响应的键值对象,前端解析时按Key取数即可。中间件顺序很关键,必须在UseOcelot前注册,否则请求已进入网关转发逻辑,头部修改不会生效。通过这种组合,C#工程师可以用少量代码获得企业级网关的大部分能力。
四、限流与鉴权集成要点
网关层限流能防止恶意刷接口。Ocelot内置基于客户端白名单的RateLimit选项,可在路由级或全局开启。配合IdentityServer等认证服务,还能在网关统一校验Bearer令牌,下游服务只认内部可信头。
在Route中添加RateLimitOptions,指定每秒允许的请求数和客户端策略。若需JWT校验,可在Gateway项目安装认证包,用builder.Services.AddAuthentication().AddJwtBearer(),并在中间件管道里先验证再转发。这样即使某个下游服务疏漏,外部也无法绕过网关直达。
{
"Routes": [
{
"DownstreamPathTemplate": "/api/product/{everything}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [ { "Host": "127.0.0.1", "Port": 7001 } ],
"UpstreamPathTemplate": "/product/{everything}",
"RateLimitOptions": {
"ClientWhitelist": [ "admin" ],
"Period": "1s",
"Limit": 10
}
}
],
"GlobalConfiguration": {
"RateLimitOptions": {
"DisableRateLimitHeaders": false
}
}
}
以上配置表示普通客户端每秒最多十次请求,admin白名单不受限。返回头会带上剩余配额,方便前端做友好提示。当系统规模扩大,可以把Ocelot实例本身前置在Nginx后做横向扩展,配置文件由CI统一下发,整个API入口就既灵活又可控。
C#OcelotAPI_Gateway修改时间:2026-08-02 21:00:44