使用.NET 6開發TodoList應用(23)——實現請求限流

系列導航及源程式碼

需求

Rate Limiting允許保護我們的API服務免受過多請求的連接導致的性能下降,如果請求次數超過了限制,API服務端將會拒絕後續的請求。

我們可以實現這樣的需求:限制獲取所有TodoLists為每個IP地址每小時上限為50個請求。採用的庫是AspNetCoreRateLimit。限制方式還有很多種,可以參考庫的官方文檔:IpRateLimitMiddleware

目標

實現基於IP地址獲取所有TodoListsRate LimitingThrottling。其他的規則可以參考官方文檔進行配置。

原理與思路

通過AspNetCoreRateLimit庫,我們可以實現通過幾個Header欄位實現相關的功能:

  • X-Rate-Limit-Limit:代表了Rate Limit的時段。
  • X-Rate-Limit-Remaining:代表了剩餘請求的個數。
  • X-Rate-Limit-Reset:包含了重置請求限制的時間戳資訊。

實現

引入AspNetCoreRateLimit包並進行配置

Api項目中新建一個Extension:

  • RateLimitingServiceExtensions.cs
using AspNetCoreRateLimit;

namespace TodoList.Api.Extensions;

public static class RateLimitingServiceExtensions
{
    public static void ConfigureApiVersioning(this IServiceCollection services)
    {
        // 當然也可以使用Configuration的方式讀取RateLimit規則
        var rateLimitRules = new List<RateLimitRule>
        {
            new ()
            {
                Endpoint = "*",
                Limit = 2,
                Period = "5m"
            }
        };
        services.Configure<IpRateLimitOptions>(options => options.GeneralRules = rateLimitRules);

        // 使用記憶體作為存儲
        services.AddSingleton<IRateLimitCounterStore, MemoryCacheRateLimitCounterStore>();
        services.AddSingleton<IIpPolicyStore, MemoryCacheIpPolicyStore>();
        services.AddSingleton<IRateLimitConfiguration, RateLimitConfiguration>();
        services.AddSingleton<IProcessingStrategy, AsyncKeyLockProcessingStrategy>();
    }
}

Program中配置並添加中間件:

  • Program.cs
// 省略其他...
builder.Services.AddMemoryCache();
builder.Services.ConfigureRateLimiting();
builder.Services.AddHttpContextAccessor();
// ...

app.UseHttpsRedirection();
// 添加中間件
app.UseIpRateLimiting();
app.UseAuthorization();

驗證

為了去除別的干擾資訊,我把之前添加的快取中間件暫時注釋掉了。啟動Api項目,執行獲取所有TodoLists的請求:

  • 請求
    image

  • 響應
    第一次請求能正確返回結果,我們查看返回的Header資訊:
    image
    再發起第二次請求,注意X-Rate-Limit-Remaining欄位的值:
    image
    再發起第三次請求,返回如下:
    image
    Header資訊如下:
    image

可以看到請求規則的上限已經達到,會返回429狀態碼。當我們在X-Rate-Limit-Reset標記的時間後再去請求介面,可以正常返回結果。

總結

在本文中,我們實現了Rate Limiting的需求。關於這個庫的更多使用方式,可以參考庫的官方文檔:IpRateLimitMiddleware。下一篇我們開始進入認證和鑒權的內容。

參考資料

  1. AspNetCoreRateLimit
  2. IpRateLimitMiddleware