目录
当API被频繁请求会导致的资源耗尽和性能下降问题。API限流可以确保系统在面对大量请求时,能够保持稳定的度响应速和资源利用率,提高系统的可用性和稳定性,起到保护后端服务的作用。
具体来说,API限流可以起到以下作用:
- 防止请求暴增:在某些情况下,如大促销活动、热门事件等,可能会导致大量请求瞬间涌入系统,这时候限流可以有效地控制请求速率,避免系统崩溃。
- 防止超载:当系统负载较高时,限流可以阻止新的请求进入系统,以避免系统超载,这样可以保护系统资源,确保服务的稳定性和可用性。
- 防止恶意攻击:限流可以阻止恶意攻击,如DDoS攻击等,通过限制请求速率,可以减轻系统的攻击压力,保护系统不受恶意攻击的影响。
- 优化系统性能:限流可以确保系统请求速率在可承受范围内,避免资源耗尽和性能下降,同时也可以优化系统性能,提高系统响应速度和吞吐量。
在.Net 7版本之前,我们实现API限流,一般都会借助第三方中间件、或者自己编写。但.Net 7新增了功能:中间件提供速率限制中间件,Microsoft.AspNetCore.RateLimiting。
.NET 7提供了四个速率控制器算法:
- 固定窗口限制器
- 滑动窗口限制器
- 令牌桶限制程序
- 并发限制器
1. 固定窗口限制器
固定窗口限制器指设置固定时间允许的请求次数
创建一个登录的限制器
builder.Services.AddRateLimiter(_ => _
// 添加一个基于固定时间窗口的速率限制器
.AddFixedWindowLimiter(policyName: RateLimiterPolicyName.LoginPolicy, options =>
{
options.PermitLimit = 1; // 指定时间内允许的请求数
options.Window = TimeSpan.FromSeconds(10); // 每10秒钟限制一次
options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst; // 队列处理顺序(先进先处理)
options.QueueLimit = 10;// 队列最大长度
}));
var app = builder.Build();
app.UseRateLimiter(); // 这里千万不能忘记启动限流的中间件
2. 滑动窗口限制器
设定一个时间段内最大请求,并分为N个时间窗口,每过期一个时间窗口,回收过期的时间窗口的用掉的请求次数。
builder.Services.AddRateLimiter(_ => _
// 启动滑动窗口限制器
.AddSlidingWindowLimiter(policyName: RateLimiterPolicyName.LoginPolicy, options =>
{
options.PermitLimit = 100;
options.Window = TimeSpan.FromSeconds(30);
options.SegmentsPerWindow = 3; // 分为3段,每一段为10秒
options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
options.QueueLimit = 10;
}));
var app = builder.Build();
app.UseRateLimiter();
3. 令牌桶限制程序
设定一个时间段内最大请求,并分为N个时间窗口,并且每过期一个时间窗口,回收固定的请求次数
builder.Services.AddRateLimiter(_ => _
// 启动令牌桶限制程序
.AddTokenBucketLimiter(policyName: "token", options =>
{
options.TokenLimit = 100;
options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
options.QueueLimit = 10;
options.ReplenishmentPeriod = TimeSpan.FromSeconds(10); // 令牌周期时间段为10秒
options.TokensPerPeriod = 20; // 回收的数量为20个
options.AutoReplenishment = true;
}));
var app = builder.Build();
app.UseRateLimiter();
4. 并发限制器
限制同一个时间,允许同时处理的数量,不限制总的处理数量
builder.Services.AddRateLimiter(_ => _
// 启动并发限制器
.AddConcurrencyLimiter(policyName: "Concurrency", options =>
{
options.PermitLimit = 10; // 允许并发10个
options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
options.QueueLimit = 10;
}));
var app = builder.Build();
app.UseRateLimiter();
写好相关的限流后,我们可通过[EnableRateLimiting]和 [DisableRateLimiting]属性,来配置是否开启限流。
[HttpPost]
[EnableRateLimiting(RateLimiterPolicyName.LoginPolicy)] //使用限流