ASP.NET Core WebAPI 限流与节流实战:高性能 API 防护与优化策略
2025-12-12 315 0
为什么要限流与节流?
随着业务成长,高并发、大流量请求成为 WebAPI 面临的常见挑战。如果没有控制 API 的访问频率,会出现:
- 服务器 CPU/内存飙升
- 数据库连接耗尽
- 服务响应延迟扩大
- 恶意攻击或流量突发导致宕机
因此,限流与节流是保障 API 稳定性的重要手段。
限流与节流的核心概念
限流(Rate Limiting)
限流是对单位时间内允许访问的最大请求次数进行控制。常见策略如:每秒 N 次、每分钟 N 次、每小时 N 次。应用场景:
- 防止恶意刷接口
- 分配公平访问资源
- 避免峰值流量冲垮系统
节流(Throttling)
节流是对请求执行频率进行控制,通过延迟处理将高频请求“平滑”分布。通常用于:
- 控制请求峰值
- 减少重复运算
- 优化资源利用
与限流相比,节流更强调平缓处理,而非简单拒绝请求。
ASP.NET Core WebAPI 如何实现限流/节流?
ASP.NET Core 6.0+ 自带 Rate Limiting 中间件,可通过配置策略实现多种流控需求。
使用 ASP.NET Core 内置限流中间件
1. 添加 NuGet 包
dotnet add package Microsoft.AspNetCore.RateLimiting
2. 配置限流策略(Program.cs)
using Microsoft.AspNetCore.RateLimiting;
using System.Threading.RateLimiting;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRateLimiter(options =>
{
// 全局限流策略
options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(httpContext =>
RateLimitPartition.GetFixedWindowLimiter(
partitionKey: httpContext.Connection.RemoteIpAddress?.ToString() ?? "unknown",
factory: key => new FixedWindowRateLimiterOptions
{
PermitLimit = 100, // 每窗口允许的最大请求数
Window = TimeSpan.FromMinutes(1), // 窗口周期
QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
QueueLimit = 0
})
);
options.OnRejected = async (context, token) =>
{
context.HttpContext.Response.StatusCode = 429;
await context.HttpContext.Response.WriteAsync("请求过于频繁,请稍后再试。");
};
});
var app = builder.Build();
app.UseRateLimiter();
app.MapGet("/api/data", () => "限流测试接口");
app.Run();
解释:
- PermitLimit(许可数):每分钟最多允许 100 次请求。
- 超出请求会返回 429(Too Many Requests)。
- 基于客户端 IP 作为限流 Key。
自定义节流策略案例
节流模式可以采用滑动窗口、漏桶算法等逻辑。
builder.Services.AddRateLimiter(options =>
{
options.AddPolicy("SlidingWindow", httpContext =>
RateLimitPartition.GetSlidingWindowLimiter(
partitionKey: httpContext.User?.Identity?.Name ?? httpContext.Connection.RemoteIpAddress?.ToString(),
factory: key => new SlidingWindowRateLimiterOptions
{
PermitLimit = 50,
Window = TimeSpan.FromSeconds(30),
SegmentsPerWindow = 6,
QueueLimit = 10,
QueueProcessingOrder = QueueProcessingOrder.OldestFirst
}));
});
滑动窗口策略优势
- 更精细控制瞬时请求峰值
- 避免集中重置导致“爆发式”短时间请求
按接口分组设置策略
app.UseRateLimiter(new RateLimiterOptions
{
RejectionStatusCode = 429,
OnRejected = async (context, token) =>
{
await context.HttpContext.Response.WriteAsync("当前请求被限流");
}
});
app.MapGet("/api/user", () => "用户接口")
.RequireRateLimiting("UserPolicy");
app.MapGet("/api/order", () => "订单接口")
.RequireRateLimiting("OrderPolicy");
可以针对不同 API 路径制定不同策略,如:
/api/user每分钟 30 次/api/order每分钟 80 次
结合缓存与 Redis 实现分布式限流
在分布式场景下,可使用 Redis 保存请求计数器,实现跨服务限流。示例伪代码:
// 伪代码逻辑
var count = await redis.StringIncrementAsync(key);
if (count == 1)
redis.KeyExpire(key, TimeSpan.FromMinutes(1));
if (count > limit)
return 429;
Redis 可用于:
- 多实例共享限流状态
- 实现分布式滑动窗口
限流与节流的最佳实践
- 区分业务场景设定策略
- 优先采取平滑节流再拒绝模式
- 返回明确提示(HTTP 429)
- 在生产环境监控限流效果
- 避免对静态内容进行不必要限流
总结
ASP.NET Core 提供了强大而灵活的限流/节流中间件,可结合策略实现不同性能目标。无论是抵御高并发、保护下游服务还是提升用户体验,良好的流控策略都是高质量 WebAPI 的必备能力。