使用.NET 6開發TodoList應用(23)——實現請求限流
系列導航及源程式碼
需求
Rate Limiting
允許保護我們的API服務免受過多請求的連接導致的性能下降,如果請求次數超過了限制,API服務端將會拒絕後續的請求。
我們可以實現這樣的需求:限制獲取所有TodoLists
為每個IP地址每小時上限為50個請求。採用的庫是AspNetCoreRateLimit
。限制方式還有很多種,可以參考庫的官方文檔:IpRateLimitMiddleware
目標
實現基於IP地址獲取所有TodoLists
的Rate Limiting
和Throttling
。其他的規則可以參考官方文檔進行配置。
原理與思路
通過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
的請求:
-
請求
-
響應
第一次請求能正確返回結果,我們查看返回的Header資訊:
再發起第二次請求,注意X-Rate-Limit-Remaining
欄位的值:
再發起第三次請求,返回如下:
Header資訊如下:
可以看到請求規則的上限已經達到,會返回429
狀態碼。當我們在X-Rate-Limit-Reset
標記的時間後再去請求介面,可以正常返回結果。
總結
在本文中,我們實現了Rate Limiting
的需求。關於這個庫的更多使用方式,可以參考庫的官方文檔:IpRateLimitMiddleware。下一篇我們開始進入認證和鑒權的內容。