Pla*_*pus 5 .net c# filtering rate-limiting .net-7.0
我必须使用 .NET 7 新的速率限制中间件对公共端点实施速率限制。
现在我已经选择了固定窗口速率限制器。我在网上找到了许多不同的实现,但我发现在 IP/客户端上实现任何类型的过滤的唯一实现是使用我不想要的 globalLimiter 。
我有很多端点,并且我希望在 2 个公共端点上有 2 个不同的限制器。
我想要的是以下 2 个实现的混合,这允许我命名策略以仅在端点上实现它,并且速率限制为每个/客户端。
builder.Services.AddRateLimiter(options =>
{
options.AddFixedWindowLimiter("myRateLimiter1", options =>
{
options.AutoReplenishment = true;
options.PermitLimit = 1;
options.Window = TimeSpan.FromSeconds(30);
});
options.AddFixedWindowLimiter("myRateLimiter12", options =>
{
options.AutoReplenishment = true;
options.PermitLimit = 1;
options.Window = TimeSpan.FromSeconds(30);
});
});
Run Code Online (Sandbox Code Playgroud)
builder.Services.AddRateLimiter(options =>
{
options.GlobalLimiter = PartitionedRateLimiter.Create<HttpContext, string>(httpContext =>
RateLimitPartition.GetFixedWindowLimiter(
partitionKey: httpContext.User.Identity?.Name ?? httpContext.Request.Headers.Host.ToString(),
factory: partition => new FixedWindowRateLimiterOptions
{
AutoReplenishment = true,
PermitLimit = 1,
QueueLimit = 0,
Window = TimeSpan.FromSeconds(30)
}));
});
Run Code Online (Sandbox Code Playgroud)
我还发现这个实现可以完成这项工作,但也找不到如何添加过滤
app.UseRateLimiter(new RateLimiterOptions
{
OnRejected = (context, _) =>
{
if (context.Lease.TryGetMetadata(MetadataName.RetryAfter, out var retryAfter))
{
context.HttpContext.Response.Headers.RetryAfter =
((int)retryAfter.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo);
app.Logger.LogWarning("Rate limit exceeded, retry after {RetryAfter} seconds", retryAfter.TotalSeconds);
}
context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;
return new ValueTask();
}
}
.AddFixedWindowLimiter("myRateLimiter1", options =>
{
options.AutoReplenishment = true;
options.PermitLimit = 1;
options.Window = TimeSpan.FromSeconds(10);
options.QueueLimit = 0;
}).AddFixedWindowLimiter("myRateLimiter2", options =>
{
options.AutoReplenishment = true;
options.PermitLimit = 1;
options.Window = TimeSpan.FromSeconds(10);
options.QueueLimit = 0;
}));
Run Code Online (Sandbox Code Playgroud)
通过以下方式添加限制器RateLimiterOptions.AddPolicy
:
builder.Services.AddRateLimiter(options =>
{
options.AddPolicy("myRateLimiter1", context => RateLimitPartition.GetFixedWindowLimiter(
partitionKey: context.User.Identity?.Name ?? context.Request.Headers.Host.ToString(),
factory: partition => new FixedWindowRateLimiterOptions
{
AutoReplenishment = true,
PermitLimit = 1,
QueueLimit = 0,
Window = TimeSpan.FromSeconds(30)
}));
// and the second one
});
Run Code Online (Sandbox Code Playgroud)