简体   繁体   English

.NET 7 速率限制 - 客户端速率限制

[英].NET 7 Rate Limiting - Rate limit by Client

I have to implement rate limiting to public endpoints using.Net 7 new Rate limiting Middleware.我必须使用 .Net 7 新的速率限制中间件对公共端点实施速率限制。
For now I've settled on a fixedWindow rate limiter.现在我已经确定了一个 fixedWindow 速率限制器。 I've found many differents implementations online, but the only ones I found implementing any kind of filtering on IP/Client are using the globalLimiter which I dont want.我在网上发现了许多不同的实现,但我发现唯一在 IP/客户端上实现任何类型的过滤的是使用我不想要的 globalLimiter。
I have many endpoints and I want 2 different limiters on 2 of my public endpoints.我有很多端点,我想在我的 2 个公共端点上使用 2 个不同的限制器。
What I want is a mix of the 2 following implementation, which allows me to name the policy to implement it on only the endpoints, and the rate limiting to be per/client.我想要的是以下 2 个实现的混合,它允许我命名策略以仅在端点上实现它,并将速率限制为每个/客户端。

2 different policies I can assign to each of my endpoints:我可以为每个端点分配 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);
    });
});

Filtering clients that is implemented globally过滤全局实施的客户端

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

I also found this implementation that does the job but cant find how to add filtering either我还发现这个实现可以完成这项工作,但也找不到如何添加过滤

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

Add your limiters via RateLimiterOptions.AddPolicy :通过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
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM