C# API速率限制方法 C# ASP.NET Core如何实现Rate Limiting

来源:这里教程网 时间:2026-02-21 17:41:43 作者:

ASP.NET Core 6+ 内置
AddRateLimiter
是首选方案

ASP.NET Core 6 开始原生支持速率限制,无需第三方包(如 AspNetCoreRateLimit),配置更轻、扩展性更好。它基于策略(

RateLimiterOptions
)和限流器(如
SlidingWindowLimiter
TokenBucketLimiter
)实现,与中间件生命周期深度集成。

常见错误是直接在

Program.cs
中调用
AddRateLimiter
后忘记启用中间件,或策略名称拼写不一致导致 429 不触发。

必须在
app.UseRateLimiter()
之前注册服务,且顺序不能颠倒
策略名(如
"sliding"
)需与
RequireRateLimiting("sliding")
中的字符串完全一致
SlidingWindowLimiter
更适合突发流量控制;
TokenBucketLimiter
更适合平滑匀速放行
限流键(
KeyGenerator
)默认按客户端 IP,若需按 API key 或用户 ID,必须自定义
HttpContext
提取逻辑

SlidingWindowLimiter
配置关键参数说明

滑动窗口是最常用策略,但参数含义容易误解:

PermitLimit
是窗口内允许请求数,
Window
是窗口时长,而
QueueProcessingOrder
QueueLimit
控制排队行为——不是所有场景都需要排队。

PermitLimit = 100
+
Window = TimeSpan.FromMinutes(1)
表示每分钟最多 100 次请求,不是“每 60 秒清零”,而是滚动统计
设置
QueueLimit = 10
后,超出限流的请求会排队,但超时由
QueueTimeout
控制(默认 10 秒),超时仍返回 429
若禁用排队(
QueueLimit = 0
),所有超额请求立即 429,响应更快,适合低延迟敏感接口
ReplenishmentPeriod
仅对
TokenBucketLimiter
有效,滑动窗口中设了也无效

如何按用户身份(而非 IP)做限流

默认限流键只取

HttpContext.Connection.RemoteIpAddress
,要切换到用户维度,必须重写
KeyGenerator
,并在认证后读取用户标识。JWT 或 Cookie 认证均可支持,但要注意未认证请求的 fallback 处理。

在策略配置中传入自定义
KeyGenerator
函数,例如提取
HttpContext.User.FindFirst("sub")?.Value
未登录用户建议 fallback 到 IP,避免匿名用户共享同一限流桶:用
HttpContext.User.Identity.IsAuthenticated ? userId : ip
若使用
[Authorize]
特性,确保
UseAuthentication()
UseRateLimiter()
之前调用,否则
User
为空
注意:
User
对象在限流中间件执行时已解析完成,但自定义声明需在
AddJwtBearer
AddCookie
中显式映射

生产环境必须检查的三个隐藏问题

本地测试通过不代表线上可用。分布式部署、高并发压测、日志埋点缺失,常让限流失效却不报错。

默认内存限流器(
MemoryRateLimiter
)不支持多实例共享状态,K8s 多 Pod 场景下必须换用
RedisRateLimiter
并注入
IConnectionMultiplexer
未开启详细日志时,限流拒绝不会输出任何信息,建议在
Program.cs
中配置:
builder.Logging.AddConsole().AddFilter("Microsoft.AspNetCore.RateLimiting", LogLevel.Debug)
前端可能忽略
X-RateLimit-Remaining
等响应头,但这些头默认不启用,需手动调用
EnableRateLimitHeaders(true)
才会写入
限流策略本身不难配,真正复杂的是键的设计粒度、跨进程状态同步、以及拒绝时的用户体验衔接——比如是否返回友好的 JSON 错误体,而不是裸 429 HTML 页面。

相关推荐