2016-08-05 58 views
2

我想創建一個簡單的計算器服務,有一個單一的方法來添加數字。此Add方法應該是async,並且必須限制在給定時間進行的併發呼叫數量。例如,每秒不超過5個併發呼叫。如果超出費率限制,則呼叫應該引發異常。如何使用Observable構建限速API?

類應該是這樣的:

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 Add(IObservable values)'。 – Enigmativity

+0

@Enigmativity你是什麼意思與「避免混合monads」?另外,你認爲使用Rx來限制API是有意義的嗎? – SuperJMN

回答

1

我不認爲在這裏使用Rx很有意義,除非您可以像Enigmativity在評論中建議的那樣將您的方法重寫爲類似public IObservable<int> Add(IObservable<Tuple<int, int>> values)的東西。

我會做的是將速率限制的關注區分爲單獨的類。這樣一來,你的代碼可能是這個樣子:

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