ThrottlingTroll 6.1.0-beta1
See the version list below for details.
dotnet add package ThrottlingTroll --version 6.1.0-beta1
NuGet\Install-Package ThrottlingTroll -Version 6.1.0-beta1
<PackageReference Include="ThrottlingTroll" Version="6.1.0-beta1" />
paket add ThrottlingTroll --version 6.1.0-beta1
#r "nuget: ThrottlingTroll, 6.1.0-beta1"
// Install ThrottlingTroll as a Cake Addin #addin nuget:?package=ThrottlingTroll&version=6.1.0-beta1&prerelease // Install ThrottlingTroll as a Cake Tool #tool nuget:?package=ThrottlingTroll&version=6.1.0-beta1&prerelease
ThrottlingTroll
Rate limiting/throttling middleware for ASP.NET and Azure Functions.
<img alt="Nuget" src="https://img.shields.io/nuget/v/ThrottlingTroll?label=current%20version">
<img alt="Nuget" src="https://img.shields.io/nuget/dt/ThrottlingTroll?label=ThrottlingTroll%20downloads"> <img alt="Nuget" src="https://img.shields.io/nuget/dt/ThrottlingTroll.AzureFunctions?label=ThrottlingTroll.AzureFunctions%20downloads"> <img alt="Nuget" src="https://img.shields.io/nuget/dt/ThrottlingTroll.AzureFunctionsAspNet?label=ThrottlingTroll.AzureFunctionsAspNet%20downloads">
Install from Nuget:
ASP.NET | Azure Functions | Azure Functions with ASP.NET Core Integration |
---|---|---|
dotnet add package ThrottlingTroll |
dotnet add package ThrottlingTroll.AzureFunctions |
dotnet add package ThrottlingTroll.AzureFunctionsAspNet |
Features
Supports ASP.NET, Azure Functions (.NET Isolated) and Azure Functions with ASP.NET Core Integration.
Ingress throttling, aka let your service automatically respond with
429 TooManyRequests
to some obtrusive clients.sequenceDiagram Client->>+YourService: #127760;HTTP alt limit exceeded? YourService-->>Client:❌ 429 TooManyRequests else YourService-->>-Client:✅ 200 OK end
Implemented as an ASP.NET Core Middleware (for ASP.NET) and as an Azure Functions Middleware (for Azure Functions).
Egress throttling, aka limit the number of calls your code is making against some external endpoint.
sequenceDiagram YourService->>+HttpClient: SendAsync() alt limit exceeded? HttpClient-->>YourService:❌ 429 TooManyRequests else HttpClient->>+TheirService: #127760;HTTP TheirService-->>-HttpClient:✅ 200 OK HttpClient-->>-YourService:✅ 200 OK end
Implemented as an HttpClient DelegatingHandler, which produces
429 TooManyRequests
response (without making the actual call) when a limit is exceeded.Propagating
429 TooManyRequests
from egress to ingress, aka when your service internally makes an HTTP request which results in429 TooManyRequests
, your service can automatically respond with same429 TooManyRequests
to its calling client.sequenceDiagram Client->>+YourService: #127760;HTTP YourService->>+TheirService: #127760;HTTP TheirService-->>-YourService:❌ 429 TooManyRequests YourService-->>-Client:❌ 429 TooManyRequests
Custom response fabrics. For ingress it gives full control on what to return when a request is being throttled, and also allows to implement delayed responses (instead of just returning
429 TooManyRequests
):sequenceDiagram Client->>+YourService: #127760;HTTP alt limit exceeded? YourService-->>YourService: await Task.Delay(RetryAfter) YourService-->>Client:✅ 200 OK else YourService-->>-Client:✅ 200 OK end
For egress it also allows ThrottlingTroll to do automatic retries for you:
sequenceDiagram YourService->>+HttpClient: SendAsync() loop while 429 TooManyRequests HttpClient->>+TheirService: #127760;HTTP TheirService-->>-HttpClient:❌ 429 TooManyRequests HttpClient-->>HttpClient: await Task.Delay(RetryAfter) end HttpClient->>+TheirService: #127760;HTTP TheirService-->>-HttpClient:✅ 200 OK HttpClient-->>-YourService:✅ 200 OK
Storing rate counters in a distributed cache, making your rate limiting policy consistent across all your computing instances. Supported distributed counter stores are:
Dynamically configuring rate limits, so that those limits can be adjusted on-the-go, without restarting the service.
IdentityIdExtractors, that allow you to limit clients individually, based on their IP-addresses, api-keys, tokens, headers, query strings, claims etc. etc.
CostExtractors, that you can use to assign custom costs to different requests. Default cost is 1, but if some of your requests are heavier than the others, you can assign higher costs to them. Allows for even greater rate limiting flexibility.
Supported rate limiting algorithms
FixedWindow. No more than PermitLimit requests are allowed in IntervalInSeconds. Here is an illustration for the case of no more than 2 requests per each 8 seconds:
<img src="https://github.com/ThrottlingTroll/ThrottlingTroll/assets/5447190/ffb0bdc8-736b-4c6f-9eb4-db54ce72e034" height="300px"/>
The typical drawback of FixedWindow algorithm is that you'd get request rate bursts at the end of each window. So specifically to cope that we have
SlidingWindow. No more than PermitLimit requests are allowed in IntervalInSeconds, but that interval is split into NumOfBuckets. The main benefit of this algorithm over FixedWindow is that if a client constantly exceedes PermitLimit, it will never get any valid response and will always get
429 TooManyRequests
. Here is an illustration for the case of no more than 2 requests per each 8 seconds with 2 buckets:<img src="https://github.com/ThrottlingTroll/ThrottlingTroll/assets/5447190/e18abb9c-d1dd-4b64-a007-220605ed03e9" height="300px"/>
In other words, with SlidingWindow your service gets a smoother request rate.
Semaphore aka Concurrency Limiter. No more than PermitLimit requests are allowed to be executed concurrently. Here is an illustration for the case of no more than 3 concurrent requests:
<img src="https://github.com/ThrottlingTroll/ThrottlingTroll/assets/5447190/0beeac73-5d35-482a-a790-a3fe9ea6e38b" height="300px"/>
If you set Semaphore's PermitLimit to 1 and use RedisCounterStore, then ThrottlingTroll will act as a distributed lock. If you add an IdentityIdExtractor (identifying requests by e.g. a query string parameter), then it will turn into named distributed locks.
How to configure and use
Configuration and usage with ASP.NET and Azure Functions is very similar yet slightly different:
ASP.NET | Azure Functions |
---|---|
How to use with ASP.NET | How to use with Azure Functions |
How to use with Azure Functions ASP.NET Core Integration |
Samples
Sample projects that demonstrate all the above concepts:
ASP.NET | Azure Functions |
---|---|
ThrottlingTrollSampleWeb | ThrottlingTrollSampleFunction |
ThrottlingTrollSampleAspNetFunction | |
ThrottlingTrollSampleDotNet6InProcDurableFunction |
Contributing
Is very much welcomed.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net6.0
- System.Runtime.Caching (>= 7.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
7.3.0 | 505 | 10/14/2024 |
7.2.0 | 621 | 8/31/2024 |
7.2.0-beta1 | 109 | 8/31/2024 |
7.1.2 | 511 | 6/12/2024 |
7.1.1 | 147 | 6/3/2024 |
7.1.0 | 133 | 6/1/2024 |
7.1.0-beta1 | 104 | 6/1/2024 |
7.0.0 | 188 | 5/15/2024 |
7.0.0-beta2 | 95 | 5/10/2024 |
7.0.0-beta1 | 107 | 5/5/2024 |
6.1.2 | 669 | 4/5/2024 |
6.1.0 | 503 | 1/28/2024 |
6.1.0-beta1 | 191 | 1/28/2024 |
6.0.0 | 585 | 12/4/2023 |
6.0.0-beta6 | 336 | 11/26/2023 |
6.0.0-beta5 | 298 | 11/26/2023 |
6.0.0-beta4 | 295 | 11/26/2023 |
6.0.0-beta3 | 288 | 11/26/2023 |
6.0.0-beta2 | 302 | 11/26/2023 |
6.0.0-beta1 | 307 | 11/25/2023 |
5.0.0 | 1,319 | 11/2/2023 |
4.0.5 | 869 | 8/27/2023 |
4.0.4 | 600 | 7/22/2023 |
4.0.2 | 517 | 7/22/2023 |
4.0.1 | 522 | 7/22/2023 |
4.0.0 | 507 | 7/22/2023 |
3.0.4 | 1,007 | 5/17/2023 |
3.0.3 | 493 | 5/15/2023 |
3.0.2 | 508 | 5/14/2023 |
3.0.1 | 517 | 5/14/2023 |
3.0.0 | 502 | 5/13/2023 |
2.0.0 | 1,050 | 4/1/2023 |
1.2.0 | 641 | 2/21/2023 |
1.1.0 | 5,936 | 1/22/2023 |
1.0.0 | 623 | 1/18/2023 |