Saturday, August 13, 2022

ASP.NET Core: Rate Limiting with .NET 7 Preview 6

With the upcoming .NET 7, there's a new NuGet package System.Threading.RateLimiting coming to manage the Rate Limiting. We can use rate limiting to protect a resource from getting overwhelmed. There is a very detailed post Announcing Rate Limiting for .NET that you definitely should read.

In this post, let's see how can we use Rate Limiting quite easily with an ASP.NET Core Application. You need to install Microsoft.AspNetCore.RateLimiting NuGet package that provides ASP.NET Core middleware for enforcing rate limiting in an application using System.Threading.RateLimiting.

Once that's installed, we need to start by defining RateLimiterOptions.
RateLimiterOptions rateLimiterOptions = new();
Here you can set up variety of things such as defining a GlobalLimiter, adding individual rate limiters and customizing the behavior when a request is rejected from a Rate Limiter.

Now let's start by adding ConcurrencyLimiter, one of the inbuilt rate limiters.
rateLimiterOptions.AddConcurrencyLimiter(policyName: "ConcurrencyLimit",
    new ConcurrencyLimiterOptions(permitLimit: 5,
        queueProcessingOrder: QueueProcessingOrder.OldestFirst,
        queueLimit: 3)); 
Next, we need to enable Rate Limiting middleware and use the RateLimiterOptions we just created.
app.UseRateLimiter(rateLimiterOptions);
Next, we can use rate limiters we have configured in our endpoints, something like below.
app.MapGet("/ToDos", () =>
{
    return TypedResults.Ok();
 
})
.RequireRateLimiting("ConcurrencyLimit");
Here note:  the global limiter will be executed first, followed by the endpoint-specific limiter, if one exists.

Now let's try to hit the rate limit on the above endpoint by making parallel requests (a lazy way of course).
HttpClient _httpClient = new HttpClient
{
    BaseAddress = new Uri("https://localhost:44378"),
};
 
List<Task<HttpResponseMessage>> tasks = new List<Task<HttpResponseMessage>>();
 
for (int i = 0; i < 10; i++)
{
    Task<HttpResponseMessage> task = _httpClient.GetAsync("/Todos");
    tasks.Add(task);
}
 
var results = new List<HttpResponseMessage>(await Task.WhenAll(tasks));
 
foreach (HttpResponseMessage item in results)
{
    Console.WriteLine(item.StatusCode);
}
And I can see an output like below.
ServiceUnavailable
If I want to change the Response Code when the Rate limit is hit (default is 503: ServiceUnavailable), I can do something like the below.
rateLimiterOptions.RejectionStatusCode = (int)HttpStatusCode.TooManyRequests;
TooManyRequests
Hope this helps.

Most importantly, a must-read.
Happy Coding.

Regards,
Jaliya

No comments:

Post a Comment