Skip to content

Latest commit

 

History

History
229 lines (185 loc) · 5.97 KB

README.md

File metadata and controls

229 lines (185 loc) · 5.97 KB

Orleans.RateLimiting

Orleans.RateLimiting is a library for Microsoft Orleans that provides a set of rate limiting algorithms for controlling the flow of requests in your distributed applications. It is designed to be easy to use and to integrate with your Orleans-based applications seamlessly. With Orleans.RateLimiting, you can ensure your applications handle a safe number of requests without the risk of overloading your system resources. RateLimiting on learn.microsoft.com and devblogs.microsoft.com

Features

  • Supports 4 types of rate limiting algorithms:
    • Fixed Window Rate Limiter
    • Concurrency Limiter
    • Sliding Window Rate Limiter
    • Token Bucket Rate Limiter
  • Easy integration with Microsoft Orleans
  • Configurable rate limiting options
  • Comprehensive documentation and examples

Installation

You can install Orleans.RateLimiting via NuGet Package Manager:

// for Client
Install-Package ManagedCode.Orleans.RateLimiting.Client
// for Server
Install-Package ManagedCode.Orleans.RateLimiting.Server

then add the following to your SiloHostBuilder or ClientBuilder:

// for Client
clientBuilder.AddOrleansRateLimiting();

// for Server
siloBuilder.AddOrleansRateLimiting();

Also if you would like to use incoming filter and Attributes, you have to add default options for Limiter:

//Add default options and IncomingFilter
siloBuilder.AddOrleansConcurrencyLimiter(options =>
{
    options.PermitLimit = 10;
    options.QueueLimit = 15;
});

//Add default options and IncomingFilter
siloBuilder.AddOrleansFixedWindowRateLimiter(options =>
{
    options.PermitLimit = 10;
    options.QueueLimit = 15;
    options.Window = TimeSpan.FromSeconds(1);
});

//Add default options and IncomingFilter
siloBuilder.AddOrleansSlidingWindowRateLimiter(options =>
{
    options.PermitLimit = 10;
    options.QueueLimit = 15;
    options.Window = TimeSpan.FromSeconds(1);
    options.SegmentsPerWindow = 2;

});

//Add default options and IncomingFilter
siloBuilder.AddOrleansTokenBucketRateLimiter(options =>
{
    options.TokenLimit = 10;
    options.QueueLimit = 15;
    options.TokensPerPeriod = 2;
    options.ReplenishmentPeriod = TimeSpan.FromSeconds(1);
});

Usage

To use Orleans.RateLimiting in your application, first configure the desired rate limiter:

var rateLimiter = _client.GetConcurrencyLimiter("test");
await rateLimiter.Configure(new ConcurrencyLimiterOptions
{
    PermitLimit = permit,
    QueueLimit = permit * 2,
    QueueProcessingOrder = QueueProcessingOrder.OldestFirst
});

Then, acquire a lease before making a request:

await using var lease = await rateLimiter.AcquireAsync();
if (lease.IsAcquired)
{
    // do something
}
else
{
    Console.WriteLine(lease.Reason); // reason why the lease was not acquired
    Console.WriteLine(lease.RetryAfter); //TimeSpan to wait before retrying
}

The following rate limiters are provided as extensions for IGrainFactory and IClusterClient

  • Fixed Window Rate Limiter
var fixedWindowRateLimiter = _factory.GetFixedWindowRateLimiter("key");
  • Concurrency Limiter
var concurrencyLimiter = _factory.GetConcurrencyLimiter("key");
  • Sliding Window Rate Limiter
var slidingWindowRateLimiter = _factory.GetSlidingWindowRateLimiter("key");
  • Token Bucket Rate Limiter
var tokenBucketRateLimiter = _factory.GetTokenBucketRateLimiter("key");

Attrubutes for Grains

You can use attributes to decorate your grain methods and apply rate limiting to them. Make sure you check configuration section for default options.

public class TestFixedWindowRateLimiterGrain : Grain, ITestFixedWindowRateLimiterGrain
{
    [FixedWindowRateLimiter] //GrainId as key, default options
    public async Task<string> Do()
    {
        await Task.Delay(TimeSpan.FromSeconds(5));
        return "Do";
    }

    [FixedWindowRateLimiter(KeyType.Key, "go")] //String as Key, default options
    public async Task<string> Go()
    {
        await Task.Delay(TimeSpan.FromSeconds(5));
        return "Go";
    }

    [FixedWindowRateLimiter(KeyType.GrainType, permitLimit:2, queueLimit:1)] //GrainType as Key, custom options, some of them are default (check Attribute)
    public async Task<string> Take()
    {
        await Task.Delay(TimeSpan.FromSeconds(5));
        return "Take";
    }
}

Attrubutes for WebAPI

You can define OrleansRateLimiterOptions with specific name.

builder.Services.AddOrleansRateLimiterOptions("ip", new FixedWindowRateLimiterOptions
{
    QueueLimit = 5,
    PermitLimit = 10,
    Window = TimeSpan.FromSeconds(1)
});

builder.Services.AddOrleansRateLimiterOptions("Anonymous", new FixedWindowRateLimiterOptions
{
    QueueLimit = 1,
    PermitLimit = 1,
    Window = TimeSpan.FromSeconds(1)
});

builder.Services.AddOrleansRateLimiterOptions("Authorized", new FixedWindowRateLimiterOptions
{
    QueueLimit = 2,
    PermitLimit = 2,
    Window = TimeSpan.FromSeconds(1)
});
        

then add middelware

app.UseOrleansIpRateLimiting(); // as earlier as possible
.....
app.UseRouting();
app.UseCors();
app.MapControllers();

//Authentication should always be placed before Authorization.
app.UseAuthentication();
app.UseAuthorization();
app.UseOrleansUserRateLimiting(); // after Authorization and Authorization
.....

Finally you can add attributes to controller or single methods:

[AuthorizedIpRateLimiter("Authorized")]
[AnonymousIpRateLimiter("Authorized")]
[InRoleIpRateLimiter("Authorized", "Admin")]
[HttpGet("get_some")]
public async Task<ActionResult<string>> GetSome()
{
    await Task.Delay(300);
    return "OK";
}

Contributing

We welcome contributions to Orleans.RateLimiting! Feel free to submit issues, feature requests, and pull requests on the GitHub repository.