Skip to content

Commit d36058d

Browse files
Add chained rate limiter example
Add example for chained rate-limiters. Resolves #2343.
1 parent 468bf0c commit d36058d

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

docs/strategies/rate-limiter.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,3 +345,46 @@ new ResiliencePipelineBuilder()
345345
});
346346
```
347347
<!-- endSnippet -->
348+
349+
It is also possible to create a rate limiter strategy using [multiple chained rate limiters](https://learn.microsoft.com/aspnet/core/performance/rate-limit#create-chained-limiters)
350+
to combine multiple rate-limiters with different configurations as shown below.
351+
352+
For example, we can configure a rate limit of 100 requests per minute that also includes a rate limit of 10 requests per second.
353+
The rate limit is partitioned by a key which could, for example, be the user ID associated with an authenticated HTTP request to
354+
apply the rate limits to each user of the system individually.
355+
356+
<!-- snippet: rate-limiter-chained -->
357+
```cs
358+
// Use the user's ID as the partition key.
359+
var partitionKey = "user-id";
360+
361+
var firstSlidingWindow = PartitionedRateLimiter.Create<ResilienceContext, string>((context) =>
362+
{
363+
return RateLimitPartition.GetSlidingWindowLimiter(partitionKey, (partitionKey) => new()
364+
{
365+
PermitLimit = 100,
366+
Window = TimeSpan.FromMinutes(1),
367+
});
368+
});
369+
370+
var secondSlidingWindow = PartitionedRateLimiter.Create<ResilienceContext, string>((context) =>
371+
{
372+
return RateLimitPartition.GetSlidingWindowLimiter(partitionKey, (partitionKey) => new()
373+
{
374+
PermitLimit = 10,
375+
Window = TimeSpan.FromSeconds(1),
376+
});
377+
});
378+
379+
// Create a rate limiter that combines the two sliding windows.
380+
var chainedRateLimiter = PartitionedRateLimiter.CreateChained(firstSlidingWindow, secondSlidingWindow);
381+
382+
// Create the pipeline using the rate limiter that chains the windows together.
383+
new ResiliencePipelineBuilder()
384+
.AddRateLimiter(new RateLimiterStrategyOptions
385+
{
386+
RateLimiter = (context) => chainedRateLimiter.AcquireAsync(context.Context),
387+
})
388+
.Build();
389+
```
390+
<!-- endSnippet -->

src/Snippets/Docs/RateLimiter.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,42 @@ public static void Usage()
5656
});
5757

5858
#endregion
59+
60+
#region rate-limiter-chained
61+
62+
// Use the user's ID as the partition key.
63+
var partitionKey = "user-id";
64+
65+
var firstSlidingWindow = PartitionedRateLimiter.Create<ResilienceContext, string>((context) =>
66+
{
67+
return RateLimitPartition.GetSlidingWindowLimiter(partitionKey, (partitionKey) => new()
68+
{
69+
PermitLimit = 100,
70+
Window = TimeSpan.FromMinutes(1),
71+
});
72+
});
73+
74+
var secondSlidingWindow = PartitionedRateLimiter.Create<ResilienceContext, string>((context) =>
75+
{
76+
return RateLimitPartition.GetSlidingWindowLimiter(partitionKey, (partitionKey) => new()
77+
{
78+
PermitLimit = 10,
79+
Window = TimeSpan.FromSeconds(1),
80+
});
81+
});
82+
83+
// Create a rate limiter that combines the two sliding windows.
84+
var chainedRateLimiter = PartitionedRateLimiter.CreateChained(firstSlidingWindow, secondSlidingWindow);
85+
86+
// Create the pipeline using the rate limiter that chains the windows together.
87+
new ResiliencePipelineBuilder()
88+
.AddRateLimiter(new RateLimiterStrategyOptions
89+
{
90+
RateLimiter = (context) => chainedRateLimiter.AcquireAsync(context.Context),
91+
})
92+
.Build();
93+
94+
#endregion
5995
}
6096

6197
public static async Task HandleRejection()

0 commit comments

Comments
 (0)