2016-08-05 2 views
2

Я хотел бы создать простую службу калькулятора, которая имеет один метод для добавления чисел. Этот метод Add должен быть async и должен ограничивать количество одновременных вызовов, совершаемых в данный момент времени. Например, не более 5 одновременных вызовов в секунду. Если предел превышен, вызов должен выдать исключение.Как построить API с ограничением скорости с помощью Observables?

Класс должен быть как:

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

Любые идеи? Я бы хотел реализовать его с помощью Reactive Extensions, но если лучше использовать другую стратегию, я бы придерживался этого! Спасибо!

+0

есть несколько идей в этой статье (http://stackoverflow.com/a/36933908/3407841), которые могут вам помочь. – leetibbett

+0

Вы должны действительно избегать смешивания монад. Я думаю, было бы легче понять это, если бы у вас была эта подпись: 'public IObservable Добавить (IObservable значений)'. – Enigmativity

+0

@ Энигматичность Что значит «избегать смешивания монад»? Кроме того, как вы думаете, имеет смысл использовать Rx для ограничения скорости API? – SuperJMN

ответ

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

Я также хочу, чтобы противоположное потребление API с ограничением скорости было максимально прозрачным: http://stackoverflow.com/questions/38675713/wrapping-rate-limiting-api-call. Может быть, вы могли бы помочь. Огромное спасибо! – SuperJMN

 Смежные вопросы

  • Нет связанных вопросов^_^