在此博客中,我们将了解如何使用不同的速率限制算法,并在 .NET Web API 中使用 Microsoft.AspNetCore.RateLimiting NuGet 包实现它们。要了解有关速率限制基础知识的更多信息,请阅读下面的博客。
下面是 Microsoft.AspNetCore.RateLimiting 中间件中可用的不同速率限制算法:
让我们通过代码示例来了解它们中的每一个。
该算法计算在固定时间窗口内发出的请求数。在每个时间窗口开始时,请求计数器将重置为零。每个传入的请求都会递增计数器。
优点
缺点
下面是我们如何配置固定窗口算法并在端点级别使用它的示例。
// Add services to the container.
builder.Services.AddRateLimiter(options => {
options.AddFixedWindowLimiter("Fixed", opt => {
opt.Window = TimeSpan.FromSeconds(10);
opt.PermitLimit = 4;
opt.QueueLimit = 2;
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
});
options.RejectionStatusCode = 429;
});
app.UseRateLimiter();
[HttpGet(Name = "GetWeatherForecastWithFixedRateAlgorithm")]
[EnableRateLimiting("Fixed")]
public IEnumerable<WeatherForecast> GetWithFixedRateAlgorithm()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
此算法跟踪滑动时间窗口内最近请求的时间戳。维护每个请求的时间戳日志,然后删除滑动窗口外的时间戳。滑动窗口限制器的操作方式与固定窗口限制器非常相似,但在每个窗口内引入段。每个段都按照段间隔一个接一个地向前移动。此段间隔的计算方式为窗口时间除以每个窗口的段数。
优点
缺点
下面是滑动窗口将如何进行以及总请求限制将如何随着时间的推移而变化的图示。请注意,下面的传入请求位于段的开头,做出此假设是为了便于下面的解释。
下面是我们如何配置上述滑动窗口算法并在端点级别使用它的示例。
// Add services to the container.
builder.Services.AddRateLimiter(options => {
options.AddSlidingWindowLimiter("Sliding", opt => {
opt.PermitLimit = 100;
opt.Window = TimeSpan.FromMinutes(30);
opt.SegmentsPerWindow = 3;
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
opt.QueueLimit = 10;
});
options.RejectionStatusCode = 429;
});
app.UseRateLimiter();
[HttpGet(Name = "GetWeatherForecastWithSlidingAlgorithm")]
[EnableRateLimiting("Sliding")]
public IEnumerable<WeatherForecast> GetWithSlidingAlgorithm()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
允许激增至一定限制的请求,并以固定速率重新填充。请求使用存储桶中的令牌,而存储桶以恒定的速率重新填充。令牌桶限制器类似于滑动窗口限制器,但不是将过期段中获取的请求加回,而是在每个补充期添加固定数量的令牌。每个段添加的令牌不能将可用令牌增加到高于令牌桶限制的数字。
优点
缺点
下表显示了令牌桶限制器,其限制为 100 个令牌,补充周期为 10 秒。
以下是我们如何配置上述令牌桶算法并在端点级别使用它的示例。
// Add services to the container.
builder.Services.AddRateLimiter(options => {
options.AddTokenBucketLimiter("Token", opt => {
opt.TokenLimit = 100;
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
opt.QueueLimit = 10;
opt.ReplenishmentPeriod = TimeSpan.FromSeconds(10);
opt.TokensPerPeriod = 10; //Rate at which you want to fill
opt.AutoReplenishment = true;
});
options.RejectionStatusCode = 429;
});
app.UseRateLimiter();
[HttpGet(Name = "GetWeatherForecastWithTokenAlgorithm")]
[EnableRateLimiting("Token")]
public IEnumerable<WeatherForecast> GetWithTokenAlgorithm()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
并发限制是最简单的速率限制形式,侧重于正在处理的并发请求数。并发限制器限制并发请求的数量。每个请求将并发限制减少 1。当请求完成时,限制将增加 1。与限制指定时间段内请求总数的其他请求限制器不同,并发限制器仅限制并发请求数,而不限制间隔内的请求数。
下面是我们如何配置上述并发算法并在端点级别使用它的示例。
// Add services to the container.
builder.Services.AddRateLimiter(options => {
options.AddConcurrencyLimiter("Concurrency", opt => {
opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
opt.QueueLimit = 10;
opt.PermitLimit = 100;
});
options.RejectionStatusCode = 429;
});
app.UseRateLimiter();
[HttpGet(Name = "GetWeatherForecastWithConcurrency")]
[EnableRateLimiting("Concurrency")]
public IEnumerable<WeatherForecast> GetWithConcurrencyAlgorithm()
{
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}
至此,我们结束了这篇关于不同速率限制算法及其在 .NET Web API 中的实现的博客。在以后的博客中,让我们看看如何使用最小 API 实现这些策略。
源代码获取:公众号回复消息【code:32976
】