.NET 中 Web API 中的速率限制算法

作者:微信公众号:【架构师老卢】
8-9 18:47
59

概述:在此博客中,我们将了解如何使用不同的速率限制算法,并在 .NET Web API 中使用 Microsoft.AspNetCore.RateLimiting NuGet 包实现它们。要了解有关速率限制基础知识的更多信息,请阅读下面的博客。下面是 Microsoft.AspNetCore.RateLimiting 中间件中可用的不同速率限制算法:Fixed WindowSliding WindowToken BucketConcurrency让我们通过代码示例来了解它们中的每一个。Fixed Window算法该算法计算在固定时间窗口内发出的请求数。在每个时间窗口开始时,请求计数器将重置为零。每个

在此博客中,我们将了解如何使用不同的速率限制算法,并在 .NET Web API 中使用 Microsoft.AspNetCore.RateLimiting NuGet 包实现它们。要了解有关速率限制基础知识的更多信息,请阅读下面的博客。

下面是 Microsoft.AspNetCore.RateLimiting 中间件中可用的不同速率限制算法:

  • Fixed Window
  • Sliding Window
  • Token Bucket
  • Concurrency

让我们通过代码示例来了解它们中的每一个。

Fixed Window算法

该算法计算在固定时间窗口内发出的请求数。在每个时间窗口开始时,请求计数器将重置为零。每个传入的请求都会递增计数器。

优点

  • 实施简单。
  • 易于理解。

缺点

  • 容易受到每个时间窗口开始时请求的突发攻击

下面是我们如何配置固定窗口算法并在端点级别使用它的示例。

// 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();
}

Sliding Window算法

此算法跟踪滑动时间窗口内最近请求的时间戳。维护每个请求的时间戳日志,然后删除滑动窗口外的时间戳。滑动窗口限制器的操作方式与固定窗口限制器非常相似,但在每个窗口内引入段。每个段都按照段间隔一个接一个地向前移动。此段间隔的计算方式为窗口时间除以每个窗口的段数。

优点

  • 允许随着时间的推移实现更顺畅的速率限制。

缺点

  • 需要更多内存来存储时间戳。

下面是滑动窗口将如何进行以及总请求限制将如何随着时间的推移而变化的图示。请注意,下面的传入请求位于段的开头,做出此假设是为了便于下面的解释。

下面是我们如何配置上述滑动窗口算法并在端点级别使用它的示例。

// 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();
}

Token Bucket 算法

允许激增至一定限制的请求,并以固定速率重新填充。请求使用存储桶中的令牌,而存储桶以恒定的速率重新填充。令牌桶限制器类似于滑动窗口限制器,但不是将过期段中获取的请求加回,而是在每个补充期添加固定数量的令牌。每个段添加的令牌不能将可用令牌增加到高于令牌桶限制的数字。

优点

  • 允许突发请求,同时保持总体限制。

缺点

  • 需要跟踪令牌充值的时间戳。

下表显示了令牌桶限制器,其限制为 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();
}

Concurrency算法

并发限制是最简单的速率限制形式,侧重于正在处理的并发请求数。并发限制器限制并发请求的数量。每个请求将并发限制减少 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

相关代码下载地址
重要提示!:取消关注公众号后将无法再启用回复功能,不支持解封!
第一步:微信扫码关键公众号“架构师老卢”
第二步:在公众号聊天框发送code:32976,如:code:32976 获取下载地址
第三步:恭喜你,快去下载你想要的资源吧
阅读排行