Microsoft.AspNetCore.RateLimiting
?中间件提供速率限制(限流)中间件。
它是.NET 7 以上版本才支持的中间件,刚看了一下,确实挺好用,下面给大家简单介绍一下:
RateLimiterOptionsExtensions?类提供下列用于限制速率的扩展方法:?????
AddFixedWindowLimiter?方法使用固定的时间窗口来限制请求。 当时间窗口过期时,会启动一个新的时间窗口,并重置请求限制。
滑动窗口算法:
permitLimit
?个请求。n
?个段。n
?个段)获取的请求会添加到当前的段。 我们将倒退一个窗口最近过期时间段称为“过期的段”。令牌桶限制器与滑动窗口限制器类似,但它不会结存从过期段获取的请求数,而是在每个补充期间添加固定数量的令牌。 每个段添加的令牌数不能使可用令牌数超过令牌桶限制。 下表显示了一个令牌桶限制器,其中令牌数限制为 100 个,补充期为 10 秒。
并发限制器会限制并发请求数。 每添加一个请求,在并发限制中减去 1。 一个请求完成时,在限制中增加 1。 其他请求限制器限制的是指定时间段的请求总数,而与它们不同,并发限制器仅限制并发请求数,不对一段时间内的请求数设置上限。
????????以上介绍是参照微软学习文档,相当枯燥无味,简单总结就是以上限制器都是为了限制客户端频繁请求接口,从而导致服务器压力过大的措施,比如可以防止dos攻击。具体实现直接看代码会比较清楚:
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel((context, serverOptions) =>
{
serverOptions.Listen(IPAddress.Any, 5000);
});
builder.Services.AddRateLimiter(configureOptions =>
{
//固定窗口限制器
configureOptions.AddFixedWindowLimiter("fixed", options =>
{
//options.QueueLimit = 1;
options.PermitLimit = 3;
options.Window = TimeSpan.FromSeconds(10);
options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
});
//滑动窗口限制器
configureOptions.AddSlidingWindowLimiter(policyName: "sliding", options =>
{
options.PermitLimit = 3;
options.Window = TimeSpan.FromSeconds(10);
options.SegmentsPerWindow = 1;
options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
//options.QueueLimit = 1;
});
//令牌桶限制器
configureOptions.AddTokenBucketLimiter(policyName: "token", options =>
{
options.TokenLimit = 3;
options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
//options.QueueLimit = 1;
options.ReplenishmentPeriod = TimeSpan.FromSeconds(10);
options.TokensPerPeriod = 2;
options.AutoReplenishment = true;
});
//并发
configureOptions.AddConcurrencyLimiter("ConLimit", options =>
{
options.QueueLimit = 10; //达到并发限制进入队列排队的数量,多余会被丢弃
options.PermitLimit = 200;//并发请求最大数量
options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
});
});
// Add services to the container.
//builder.Services.AddRazorPages();
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseSwagger();
app.UseSwaggerUI(c => { });
app.UseHttpsRedirection();
//app.UseStaticFiles();
//app.UseRouting();
app.UseAuthorization();
//app.MapRazorPages();
app.MapControllers();
//使用限制器
app.UseRateLimiter();
//固定窗口限制器
static string GetTicks() => DateTime.Now.ToString("HH:mm:ss");
app.MapGet("/fixed", () => Results.Ok($"固定窗口限制器 {GetTicks()}"))
.RequireRateLimiting("fixed");
//滑动窗口限制器
app.MapGet("/sliding", () => Results.Ok($"滑动窗口限制器 {GetTicks()}"))
.RequireRateLimiting("sliding");
//令牌桶限制器
app.MapGet("/token", () => Results.Ok($"令牌桶限制器 {GetTicks()}"))
.RequireRateLimiting("token");
//并发限制器
app.MapGet("/ConLimit", () => Results.Ok($"并发限制器 {GetTicks()}"))
.RequireRateLimiting("ConLimit");
app.Run();
核心代码就这些:
运行程序,请求http://localhost:5000/fixed?,如果10s内请求大于3次就失败:
10秒后又可以正常访问:
对指定接口进行限制,只需要在指定接口上使用EnableRateLimiting特性就行:
[EnableRateLimiting("sliding")]
[HttpGet]
public string GetString()
{
return "111";
}
10秒内请求超3次就失败:
注意上面的 options.QueueLimit 被我注释了,这个主要是设置排队的请求的最大累计允许计数,如果设置了就不会报错而是等待请求,数值是具体可以同时等待的请求数。