如何使用Observables建立速率限制API? [英] How to build a rate-limiting API with Observables?
问题描述
我想创建一个简单的计算器服务,该服务具有一个添加数字的单一方法.此Add
方法应为async
,并且必须限制在给定时间进行的并发调用数.例如,每秒不超过5个并发呼叫.如果超出了速率限制,则呼叫应引发异常.
该类应为:
public class RateLimitingCalculator
{
public async Task<int> Add(int a, int b)
{
//...
}
}
有什么想法吗?我想使用Reactive Extensions来实现它,但是如果最好使用其他策略,我会坚持下去!
我不认为在这里使用Rx是有意义的,除非您可以将方法重写为public IObservable<int> Add(IObservable<Tuple<int, int>> values)
之类的内容,这是Enigmativity在评论中建议的./p>
我要做的是将对速率限制的关注分为一个单独的类.这样,您的代码可能看起来像这样:
public class RateLimitingCalculator
{
private RateLimiter rateLimiter = new RateLimiter(5, TimeSpan.FromSeconds(1));
public async Task<int> Add(int a, int b)
{
rateLimiter.ThrowIfRateExceeded();
//...
}
}
RateLimiter
的实现取决于您的确切要求,但是一个非常简单的,非线程安全的版本可能看起来像这样:
class RateLimiter
{
private readonly int rate;
private readonly TimeSpan perTime;
private DateTime secondStart = DateTime.MinValue;
private int count = 0;
public RateLimiter(int rate, TimeSpan perTime)
{
this.rate = rate;
this.perTime = perTime;
}
public void ThrowIfRateExceeded()
{
var now = DateTime.UtcNow;
if (now - secondStart > perTime)
{
secondStart = now;
count = 1;
return;
}
if (count >= rate)
throw new RateLimitExceededException();
count++;
}
}
I would like to create a simple Calculator service that has a single method to add numbers. This Add
method should be async
and has to limit the number of concurrent calls being made at a given time. For instance, no more than 5 concurrent calls per second. If the rate limit is exceeded, the call should throw an exception.
The class should be like:
public class RateLimitingCalculator
{
public async Task<int> Add(int a, int b)
{
//...
}
}
Any ideas? I would like implement it with Reactive Extensions, but if it's better to use another strategy, I would stick to it!
I don't think using Rx makes sense here, unless you can rewrite your method into something like public IObservable<int> Add(IObservable<Tuple<int, int>> values)
, as suggested by Enigmativity in a comment.
What I would do is to separate the concern of rate limiting into a separate class. That way, your code could look something like this:
public class RateLimitingCalculator
{
private RateLimiter rateLimiter = new RateLimiter(5, TimeSpan.FromSeconds(1));
public async Task<int> Add(int a, int b)
{
rateLimiter.ThrowIfRateExceeded();
//...
}
}
The implementation of RateLimiter
depends on your exact requirements, but a very simple, not-thread-safe version could look like this:
class RateLimiter
{
private readonly int rate;
private readonly TimeSpan perTime;
private DateTime secondStart = DateTime.MinValue;
private int count = 0;
public RateLimiter(int rate, TimeSpan perTime)
{
this.rate = rate;
this.perTime = perTime;
}
public void ThrowIfRateExceeded()
{
var now = DateTime.UtcNow;
if (now - secondStart > perTime)
{
secondStart = now;
count = 1;
return;
}
if (count >= rate)
throw new RateLimitExceededException();
count++;
}
}
这篇关于如何使用Observables建立速率限制API?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!