asp.net core 7+ 内置ratelimiter需显式启用中间件且顺序严格:userouting()在前、useratelimiter()居中(authentication/authorization之后、endpoints之前)、requireratelimiting()绑定策略,缺一不可;固定窗口策略中permitlimit是周期总请求数非并发数,slidingwindow无官方add扩展方法,tokenbucket参数须匹配接口响应时长与业务容忍度。

ASP.NET Core 7+ 内置 RateLimiter 能直接用,但不配策略、不调顺序、不绑定路由,它就完全不工作——不是“效果差”,是压根没触发。
为什么 AddRateLimiter() 注册了却没限流
最常见原因:只注册服务,没启用中间件,或中间件位置错。它不像 UseAuthentication() 那样靠顺序自动生效,必须显式调用 UseRateLimiter(),且顺序严格:
-
app.UseRouting()必须在UseRateLimiter()之前(否则无法解析 endpoint) -
app.UseRateLimiter()必须在UseAuthentication()/UseAuthorization()之后、UseEndpoints()之前(否则策略无法注入到 endpoint pipeline) - 漏掉
.RequireRateLimiting("fixed")或拼错策略名(大小写敏感),该路由就完全绕过限流
AddFixedWindowLimiter() 配置要点和易错参数
固定窗口是最常用也最容易误用的策略。核心不是“设个数字”,而是理解每个参数的实际行为:
-
PermitLimit是窗口内总请求数,不是并发数;设为100表示“60 秒内最多 100 次请求”,不是“同时最多 100 个请求” -
Window推荐用TimeSpan.FromMinutes(1),别硬写60000,避免单位混淆 -
QueueLimit = 0表示不排队、直接返回429;设为5时,第 101~105 个请求会进队列,按QueueProcessingOrder执行,超时或满队仍拒 - 不设
AutoReplenishment = true(默认就是true),窗口重置后计数不会自动清零,可能持续拒绝请求
为什么找不到 AddSlidingWindowLimiter()
.NET 8/9 当前(2026 年)官方 Microsoft.Extensions.RateLimiting 中,SlidingWindowRateLimiter 类存在但未暴露扩展方法——AddSlidingWindowLimiter() 这个函数根本不存在于任何 public API 中。
你看到的文档或示例里写了它,基本是误传或基于早期预览版。真实可用路径只有两个:
- 自己实现
IServerRateLimiter<tkey></tkey>,维护分段桶(如 10 个 6 秒桶),手动聚合跨段计数——逻辑复杂,时间精度、GC 暂停、节点时钟漂移都会导致不准 - 生产环境直接上 Redis + Lua:用
zset存请求时间戳,ZCOUNT+ZREMRANGEBYSCORE做滑动窗口,天然分布式、无内存泄漏风险
TokenBucketRateLimiter 的关键参数怎么设才不翻车
令牌桶适合控制突发流量,但参数不能脱离接口实际响应时间来定:
-
TokensPerPeriod和ReplenishmentPeriod共同决定平均吞吐,例如TokensPerPeriod = 10+ReplenishmentPeriod = TimeSpan.FromSeconds(1)≈ 每秒 10 次 -
PermitLimit是桶容量(最大可借令牌数),要 ≥ 接口最大允许并发数;若 P99 响应耗时 2s,又希望用户等待不超过 30s,则QueueLimit最好 ≤(int)(30 / 2)= 15,否则请求会在队列里卡死 - 单机模式下所有桶状态存在内存,集群部署必须切换为分布式存储(如 Redis),否则各节点计数不同步
真正难的从来不是“怎么写那几行配置”,而是想清楚:这个接口到底能扛住多少并发?用户愿意等几秒?失败时该返回 429 还是 503?这些业务判断,比代码多十倍。










