C# (.NET) 中的速率限制:System.Threading.RateLimiting 库
速率限制(请求速度限制)是保护 API、微服务和 Web 应用程序免受过载、DDoS 攻击和资源不受控消耗的关键机制。在 .NET 生态系统中,自 .NET 7 起,内置了 System.Threading.RateLimiting 库,它提供了灵活且高性能的工具来实现各种限制策略。
什么是速率限制以及为什么需要它?
速率限制允许控制在特定时间段内的操作数量(请求、方法调用、事务)。主要使用场景包括:
- 保护公共 API — 防止客户端滥用。
- 稳定后端 — 均匀分配数据库和外部服务的负载。
- 节约资源 — 限制对付费第三方 API 的调用。
- 确保 SLA — 保证所有用户的平等访问。
System.Threading.RateLimiting 库的主要组件
该库围绕抽象类 RateLimiter 和几个现成的实现构建:
1. TokenBucketRateLimiter(令牌桶算法)
经典算法,以指定速率(补充速率)累积令牌,并根据需要允许使用它们。适用于平滑峰值负载。
using System.Threading.RateLimiting;
var limiter = new TokenBucketRateLimiter(new TokenBucketRateLimiterOptions{ TokenLimit = 100, // 最大令牌数 TokensPerPeriod = 20, // 每个周期添加的令牌数 ReplenishmentPeriod = TimeSpan.FromSeconds(1), // 补充周期 QueueLimit = 10, // 等待队列的最大大小 QueueProcessingOrder = QueueProcessingOrder.OldestFirst});
// 使用示例using var lease = await limiter.AcquireAsync(cancellationToken: CancellationToken.None);if (lease.IsAcquired){ // 执行操作 Console.WriteLine("令牌已获取");}else{ // 处理拒绝 Console.WriteLine("超出限制,请稍后重试");}2. ConcurrencyLimiter(并发限制器)
限制同时进行的操作数量。非常适合控制对有限资源(连接池、文件描述符)的访问。
var concurrencyLimiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions{ PermitLimit = 10, // 最多 10 个并发请求 QueueLimit = 5, // 等待队列最多 5 个请求 QueueProcessingOrder = QueueProcessingOrder.NewestFirst});
// 在异步上下文中使用async Task ProcessRequestAsync(){ using var lease = await concurrencyLimiter.AcquireAsync(); if (lease.IsAcquired) { // 执行资源密集型任务 await Task.Delay(1000); }}3. FixedWindowRateLimiter(固定窗口)
最简单的算法:在固定时间间隔内允许 N 次操作(例如,每分钟 100 个请求)。窗口结束后计数器重置。
var fixedWindow = new FixedWindowRateLimiter(new FixedWindowRateLimiterOptions{ PermitLimit = 60, // 60 个请求 Window = TimeSpan.FromMinutes(1), // 在 1 分钟内 QueueLimit = 0, // 无队列 AutoReplenishment = true // 自动重置窗口});
// 检查限制RateLimitLease lease = fixedWindow.AttemptAcquire();if (lease.IsAcquired){ Console.WriteLine($"剩余尝试次数:{lease.GetAllMetadata()}");}4. SlidingWindowRateLimiter(滑动窗口)
更