Use RateLimiter to limit the number of Outbound requests in dotnet core

Every web application calls external web services and it's often desired to limit the number of requests we send to external web services in a duration of time for example we want to send a maximum of 100 requests from our application to XYZ external web service per minute so in that case, we would like to throttle the outgoing requests going to web services.

Introduction

RateLimiter is a mechanism where we throttle the number of requests and if we send too many requests then we get the HTTP status code 523 (Too Many Requests) from the external API.

rate_limiter_asp_dotnet_api.jpg

As you can see in the above diagram there are 3 processes that are trying to hit external web services and a rate limiter will limit the number of requests going to the web service.

RateLimiter Nuget Package

We will use RateLimiter Nuget Package which is a C# client side rate-limiting utility and initially developed for throttling the requests to web services but can also be used to temporally limit the usage of one shared resource. 

Features of RateLimiter


  • Easy to use
  • Fully asynchronous: lower resource usage than thread sleep
  • Cancellable via CancellationToken
  • Thread-safe so you can share time constraints object to rate limit different threads using the same resource
  • Composable: the ability to compose different rate limits in one constraint

You can check the GitHub page of the RateLimiter library as well for more details.

Let's see the sample RateLimiter in an ASP.NET Core Application

// This method gets called by the runtime. Use this method to add services to the container.

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);


    // Defines RateLimiter
    var rateLimiter = TimeLimiter.GetFromMaxCountByInterval(3, TimeSpan.FromMinutes(1));


    // Applies the RateLimiter to all the call to IStudentClient
    services
        .AddRefitClient<IStudentClient>()
         .ConfigureHttpClient(c => c.BaseAddress = new Uri("https://localhost:44391"))
         .AddHttpMessageHandler(() => rateLimiter.AsDelegatingHandler());


    services.AddSingleton(_ => rateLimiter);
}

The above code is written in the ConfigureServices method in Startup.cs file.

We also have to create an Extension method for AsDelegatingHandler() method


public static class DispatcherExtension
{
    private sealed class DispatcherDelegatingHandler : DelegatingHandler
    {
        private readonly ComposableAsync.IDispatcher _Dispatcher;


        public DispatcherDelegatingHandler(ComposableAsync.IDispatcher dispatcher)
        {
            _Dispatcher = dispatcher;
        }


        protected override Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request,
            CancellationToken cancellationToken)
        {
            return _Dispatcher.Enqueue(() =>
                base.SendAsync(request, cancellationToken), cancellationToken);
        }
    }


    public static DelegatingHandler AsDelegatingHandler(
        this ComposableAsync.IDispatcher dispatcher)
    {
        return new DispatcherDelegatingHandler(dispatcher);
    }
}

As you see above we are applying RateLimiter for all the calls going to IStudentClient and the rate is defined as 3 requests per minute. If the application sends more than 3 requests then it waits for the duration till 1 minute completes and then sends the request. You might have observed we are not using general HttpClient or WebClient to send the request and instead of using Refit Nuget Library so you can check this article regarding Refit Nuget Library which simplifies the call to external web service.



rate_limiter_live_example.jpg

As you can see in the above image the 3rd request takes time till 1 minute completes and the timer is reset again.


Conclusion

RateLimiter is required wherever we are required to call some external web service from our application because if we going to send too many requests then it can go down or send HTTP status code 523.

Hope you have understood how to use RateLimiter in any DotNet Core Application.

Share This Post

Linkedin
Fb Share
Twitter Share
Reddit Share

Support Me

Buy Me A Coffee