zijian666.WebApi.RateLimitQuota
2.2.1-beta
This is a prerelease version of zijian666.WebApi.RateLimitQuota.
dotnet add package zijian666.WebApi.RateLimitQuota --version 2.2.1-beta
NuGet\Install-Package zijian666.WebApi.RateLimitQuota -Version 2.2.1-beta
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="zijian666.WebApi.RateLimitQuota" Version="2.2.1-beta" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="zijian666.WebApi.RateLimitQuota" Version="2.2.1-beta" />
<PackageReference Include="zijian666.WebApi.RateLimitQuota" />
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add zijian666.WebApi.RateLimitQuota --version 2.2.1-beta
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
#r "nuget: zijian666.WebApi.RateLimitQuota, 2.2.1-beta"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package zijian666.WebApi.RateLimitQuota@2.2.1-beta
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=zijian666.WebApi.RateLimitQuota&version=2.2.1-beta&prerelease
#tool nuget:?package=zijian666.WebApi.RateLimitQuota&version=2.2.1-beta&prerelease
The NuGet Team does not provide support for this client. Please contact its maintainers for support.
RateLimitQuota 速率限制配额模块
概述
RateLimitQuota 是一个速率限制配额功能模块,用于在 ASP.NET Core 应用中限制接口访问频率,防止接口被过度调用。
核心特性
- 灵活的配额提供者:支持多个配额提供者,可以为不同的接口或用户设置不同的限流规则
- 可扩展的计数器:支持自定义速率计数器实现,可以使用内存、Redis 等存储方式
- 自动重试提示:当触发限流时,自动在响应头中添加
Retry-After提示客户端重试时间 - 零配置使用:通过构建器模式轻松配置和使用
快速开始
1. 实现速率计数器
实现 IRateCounter 接口来定义如何计数:
using System.Collections.Concurrent;
using zijian666.WebApi.Abstractions;
public class MemoryRateCounter : IRateCounter
{
private readonly ConcurrentDictionary<string, (int count, DateTime expire)> _cache = new();
public ValueTask<int> Increment(string key, DateTime expire)
{
var (count, _) = _cache.AddOrUpdate(key,
_ => (1, expire),
(k, item) =>
{
var (currentCount, oldExpire) = item;
// 如果已过期,重置计数
if (oldExpire < DateTime.Now)
{
return (1, expire);
}
return (currentCount + 1, oldExpire);
});
return ValueTask.FromResult(count);
}
public ValueTask<DateTime?> GetExpire(string key)
{
if (_cache.TryGetValue(key, out var value))
{
return ValueTask.FromResult<DateTime?>(value.expire);
}
return ValueTask.FromResult<DateTime?>(null);
}
}
2. 实现配额提供者
实现 IRateLimitQuotaProvider 接口来定义限流规则:
using zijian666.WebApi.Abstractions;
public class DefaultRateLimitQuotaProvider : IRateLimitQuotaProvider
{
public ValueTask<RateLimitQuota[]> Get(ApiActionContext context)
{
// 根据接口路径、用户等信息设置不同的限流规则
var quota = new RateLimitQuota
{
Key = $"rate_limit:{context.ActionDescriptor.DisplayName}", // 使用接口路径作为键
Limit = 10, // 限制为 10 次
Expire = DateTime.Now.AddSeconds(60) // 60 秒内有效
};
return ValueTask.FromResult(new[] { quota });
}
}
3. 注册服务
在 Program.cs 中注册速率限制配额功能:
using zijian666.WebApi;
var builder = WebApplication.CreateBuilder(args);
// 添加速率限制配额功能
builder.AddWebApi(webApi =>
{
webApi.AddFeature<RateLimitQuotaBuilder>(rateLimit =>
{
// 注册速率计数器类型
rateLimit.RateCounterType = typeof(MemoryRateCounter);
// 添加配额提供者
rateLimit.AddRateLimitQuotaProvider<DefaultRateLimitQuotaProvider>();
});
});
var app = builder.Build();
// 使用速率限制配额(中间件会自动注册)
app.UseWebApi();
app.Run();
高级用法
多个配额提供者
支持注册多个配额提供者,系统会依次检查所有配额:
rateLimit.AddRateLimitQuotaProvider<DefaultRateLimitQuotaProvider>();
rateLimit.AddRateLimitQuotaProvider<UserBasedRateLimitQuotaProvider>(); // 基于用户的限流
rateLimit.AddRateLimitQuotaProvider<ApiBasedRateLimitQuotaProvider>(); // 基于接口的限流
基于用户的限流
public class UserBasedRateLimitQuotaProvider : IRateLimitQuotaProvider
{
public ValueTask<RateLimitQuota[]> Get(ApiActionContext context)
{
var userId = context.HttpContext.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userId))
{
return ValueTask.FromResult(Array.Empty<RateLimitQuota>());
}
var quota = new RateLimitQuota
{
Key = $"user_rate_limit:{userId}",
Limit = 100, // 每个用户限制 100 次
Expire = DateTime.Now.AddHours(1) // 1 小时内有效
};
return ValueTask.FromResult(new[] { quota });
}
}
基于接口的限流
public class ApiBasedRateLimitQuotaProvider : IRateLimitQuotaProvider
{
public ValueTask<RateLimitQuota[]> Get(ApiActionContext context)
{
var route = context.ActionDescriptor.AttributeRouteInfo?.Template;
if (string.IsNullOrEmpty(route))
{
return ValueTask.FromResult(Array.Empty<RateLimitQuota>());
}
// 为不同的接口设置不同的限流规则
var limit = route.StartsWith("/api/admin/") ? 5 : 20;
var quota = new RateLimitQuota
{
Key = $"api_rate_limit:{route}",
Limit = limit,
Expire = DateTime.Now.AddMinutes(1) // 1 分钟内有效
};
return ValueTask.FromResult(new[] { quota });
}
}
使用 Redis 作为计数器存储
using StackExchange.Redis;
public class RedisRateCounter : IRateCounter
{
private readonly IDatabase _database;
public RedisRateCounter(IConnectionMultiplexer redis)
{
_database = redis.GetDatabase();
}
public async ValueTask<int> Increment(string key, DateTime expire)
{
var count = await _database.StringIncrementAsync(key);
// 设置过期时间
if (count == 1)
{
await _database.KeyExpireAsync(key, expire - DateTime.Now);
}
return (int)count;
}
public async ValueTask<DateTime?> GetExpire(string key)
{
var ttl = await _database.KeyTimeToLiveAsync(key);
if (ttl.HasValue)
{
return DateTime.Now.Add(ttl.Value);
}
return null;
}
}
API 参考
RateLimitQuotaBuilder
属性
RateCounterType:速率计数器类型,必须实现IRateCounter接口
方法
AddRateLimitQuotaProvider<T>():添加一个配额提供者(泛型版本)AddRateLimitQuotaProvider(Type type):添加一个配额提供者(类型版本)
IRateCounter
方法
Increment(string key, DateTime expire):对指定的键进行计数,并设置过期时间,返回当前计数GetExpire(string key):获取指定键的过期时间
IRateLimitQuotaProvider
方法
Get(ApiActionContext context):根据上下文获取限流配额数组
RateLimitQuota
属性
Key:资源键,用于标识限流资源Limit:限制频率,超过此值将触发限流Expire:过期时间,超过此时间计数将重置
RateLimitQuotaException
当触发限流时,会抛出 RateLimitQuotaException 异常,HTTP 状态码为 429 (Too Many Requests)。
工作原理
服务注册阶段(
ConfigureServices):- 注册速率计数器类型(如果指定)
- 注册配额提供者
- 注册中间件为单例服务
中间件处理阶段(
Use):- 获取所有注册的配额提供者
- 获取速率计数器实例
- 对每个配额提供者获取限流配额
- 对每个配额进行计数检查
- 如果超过限制,抛出
RateLimitQuotaException并在响应头中添加Retry-After
异常处理:
RateLimitQuotaException会被异常处理中间件捕获- 返回 HTTP 429 状态码
- 响应头中包含
Retry-After提示客户端重试时间
最佳实践
选择合适的计数器存储:
- 单机应用:使用内存计数器(如
MemoryRateCounter) - 分布式应用:使用 Redis 等分布式缓存作为计数器存储
- 单机应用:使用内存计数器(如
合理设置限流规则:
- 根据接口的重要性和性能要求设置不同的限流阈值
- 考虑用户类型(普通用户、VIP 用户等)设置不同的限流规则
配额键的设计:
- 使用有意义的键名,便于调试和监控
- 考虑使用组合键(如
user:{userId}:api:{route})来区分不同的限流维度
错误处理:
- 确保
IRateCounter实现是线程安全的 - 在计数器实现中妥善处理异常情况
- 确保
注意事项
- 必须注册至少一个
IRateCounter实现,否则会抛出异常 - 必须注册至少一个
IRateLimitQuotaProvider实现,否则限流功能不会生效 RateLimitQuotaException的StackTrace属性返回null,以减少异常信息泄露- 限流检查在中间件管道中执行,确保在路由和认证之后执行
示例项目
更多使用示例请参考:
example/WebApiDemo8:基础限流示例
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
-
net6.0
- zijian666.WebApi.Abstractions (>= 2.2.1-beta)
- zijian666.WebApi.Core (>= 2.2.1-beta)
-
net7.0
- zijian666.WebApi.Abstractions (>= 2.2.1-beta)
- zijian666.WebApi.Core (>= 2.2.1-beta)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on zijian666.WebApi.RateLimitQuota:
| Package | Downloads |
|---|---|
|
zijian666.WebApi
用于快速创建简单易用的标准化WebApi项目 |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.2.1-beta | 101 | 5/31/2026 |
UPLOGS.md