商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > C#如何实现接口限流_C# ASP.NET Core内置RateLimiter中间件【前沿】

C#如何实现接口限流_C# ASP.NET Core内置RateLimiter中间件【前沿】

  发布于2026-07-09 阅读(0)

扫一扫,手机访问

限流这事儿,.NET 生态里早就给你备好了现成的轮子——Microsoft.Extensions.RateLimiting,从 .NET 7 开始内置,线程安全,支持分布式,中间件注册也极简。换句话说,别再自己手写个 TokenBucketLimiter 类了,费力不讨好。

C#如何实现接口限流_C# ASP.NET Core内置RateLimiter中间件【前沿】

为什么不用自己写 TokenBucketLimiter 类

手写一个令牌桶,细节太容易翻车了。比如 Interlocked 的竞态处理没做好,系统时间回拨导致令牌误补,突发流量下令牌预分配逻辑写漏——这些都是坑。更隐蔽的问题是,很多人习惯用 DateTime.Now,一到容器环境或者跨时区部署就出问题。官方实现默认用 DateTimeOffset.UtcNow,底层已经用无锁队列加上高精度时间戳封装好了。你手写的类,压测时可能 QPS 一过 500 就开始丢统计,而 TokenBucketRateLimiter 全程稳如狗。

AddRateLimiter 必须配 IDistributedCache 才能多实例生效

单机跑当然没问题,但一旦部署多个 API 实例,没接缓存就退化成“每台机器各自限流”,等于没限。常见错误是只调了 services.AddRateLimiter() 却忘了注册缓存:

  • 内存模式(仅开发/单实例):services.AddMemoryCache() 必须在 AddRateLimiter() 之前
  • Redis 分布式模式:services.AddStackExchangeRedisCache(opt => opt.Configuration = "your-redis-conn"),且需确保 Redis 可写
  • 若用 TokenBucketRateLimiter 但没配 IDistributedCache,它会静默降级为内存模式,日志里不会报错,但线上扩实例后限流就失效了——你可能很久之后才发现

PermitLimit 不是 QPS,而是并发请求数上限

这个参数最容易设错。举个例子:接口平均响应 300ms,P99 达到 1.2s,你设 PermitLimit = 10,看起来像是“每秒最多 10 次”,实际含义是“最多 10 个请求同时卡在处理中”。如果突发 15 个请求进来,前 10 个拿令牌执行,后 5 个立刻排队或被拒——取决于你设的 QueueLimit

合理设置要注意几个要点:

  • PermitLimit 至少 ≥ 接口最大容忍并发数(可以参考线程池当前活跃数或者数据库连接池上限)
  • TokensPerPeriodReplenishmentPeriod 共同决定平均吞吐,比如 TokensPerPeriod = 60 + ReplenishmentPeriod = TimeSpan.FromMinutes(1) ≈ 平均 1 QPS,但允许短时突发
  • QueueLimit 别设太高:假设接口平均耗时 500ms,设 20 就意味着第 21 个请求可能排队 10 秒才失败,应取 Math.Min(5, (int)(30 / 0.5)) 这类保守值

中间件顺序错一个位置,限流就完全不触发

注册阶段和中间件阶段必须严格按顺序来,否则限流形同虚设:

  • 注册阶段(Program.cs):AddMemoryCache()AddStackExchangeRedisCache()AddRateLimiter()AddControllers()
  • 中间件阶段(app.Use...):UseRouting()UseRateLimiter()UseEndpoints()
  • 漏掉 UseRateLimiter() 或把它放在 UseRouting() 之前,所有请求都绕过限流;放在 UseEndpoints() 之后,则 endpoint 已经执行完了
  • 如果你还用了 UseAuthorization()UseAuthentication()UseRateLimiter() 必须在它们之后、UseEndpoints() 之前

真正麻烦的不是配置本身,而是限流策略和接口真实响应时间的耦合——PermitLimit 设小了影响可用性,设大了失去保护意义;ReplenishmentPeriod 设短了抖动大,设长了无法应对突发。上线前一定要用真实链路压测,而不是只看单接口的 BenchMark 数据。

本文转载于:https://www.php.cn/faq/2404607.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注