如何使用Observables构建速率限制API?

时间:2016-08-05 11:23:49

标签: c# .net async-await system.reactive rate-limiting

我想创建一个简单的Calculator服务,它有一个方法来添加数字。此Add方法应为async,并且必须限制在给定时间进行的并发调用的数量。例如,每秒不超过5个并发呼叫。如果超过了速率限制,则调用应抛出异常。

班级应该是:

public class RateLimitingCalculator
{
    public async Task<int> Add(int a, int b) 
    {
        //...
    }
}

有什么想法吗?我想用Reactive Extensions实现它,但如果使用其他策略更好,我会坚持下去! 谢谢!

1 个答案:

答案 0 :(得分:1)

我不认为在这里使用Rx是有意义的,除非你可以将你的方法重写为public IObservable<int> Add(IObservable<Tuple<int, int>> values),如评论中的Enigmativity所示。

我要做的是将速率限制的关注分成一个单独的类。这样,您的代码可能如下所示:

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++;
    }
}