2013-06-05 154 views
3

我寫了一個API速率限制器,可以與Last.fm的API一起使用。API速率限制器

Last.fm的Tos指出,我不能每秒發出超過5個請求,每秒發起IP地址的平均時間爲5分鐘。

這裏是我寫的類:

public class RateLimiter 
{ 
    private static readonly List<DateTime> _requests = new List<DateTime>(); 

    private const double _perMillisecond = 1000.1; 
    private const int _rateLimit = 5; 
    private const int _rateLimitCooldownMs = 500; 

    public static void CheckLimiter() 
    { 
     _requests.Add(DateTime.Now); 

     var requestsDuringRateLimit = _requests.Where(w => (DateTime.Now - w).TotalMilliseconds < _perMillisecond).ToArray(); 

     if (requestsDuringRateLimit.Count() >= _rateLimit) 
     { 
      Thread.Sleep(_rateLimitCooldownMs); 
      _requests.Clear(); 
      Console.Clear(); 
     } 
    } 
} 

CheckLimiter方法是HttpWebRequest之前調用啓動,則此限制API請求的好方法?

回答

2

在我看來這很好。除此之外,此代碼中存在一個錯誤。這是因爲如果每個請求都相繼完成超過一秒鐘,該怎麼辦?它永遠不會進入該if塊。因此,某種memory leak,因爲_requests將隨着時間的推移而變大,並且如果我的場景總是發生,可能永遠不會被清除。

例子:

for (int i = 0; i < 100; i++) 
{ 
    RateLimiter.CheckLimiter(); 
    Thread.Sleep(2000); 
} 

你可以做的是去除你_requests被超過喜歡加入這一行,在你的方法結束1秒規則條目。

if (_requests.Count != 0) 
{ 
    //remove irrelevant/expired entries 
    _requests.RemoveAll(date => (DateTime.Now - date).TotalMilliseconds >= _perMillisecond); 
} 
+0

是的,我注意到,我發佈後......謝謝! :) – jjdev80

1

我寫了一個庫RateLimiter來處理這種約束。我們提出的解決方案的主要優點是它是異步和可取消的。另一個特點是你可以編寫約束來構建複雜的約束。

樣品:

var timeconstraint = TimeLimiter.GetFromMaxCountByInterval(5, TimeSpan.FromSeconds(1)); 

for(int i=0; i<1000; i++) 
{ 
    await timeconstraint.Perform(ConsoleIt); 
}  

.... 
private Task ConsoleIt() 
{ 
    Trace.WriteLine(string.Format("{0:MM/dd/yyy HH:mm:ss.fff}", DateTime.Now)); 
    return Task.FromResult(0); 
} 

組成:

var constraint = new CountByIntervalAwaitableConstraint(5, TimeSpan.FromSeconds(1)); 

//Create second constraint: one time each 100 ms 
var constraint2 = new CountByIntervalAwaitableConstraint(1, TimeSpan.FromMilliseconds(100)); 

//Compose the two constraints 
var timeconstraint = TimeLimiter.Compose(constraint, constraint2); 

//Use it 
for(int i=0; i<1000; i++) 
{ 
    await timeconstraint.Perform(ConsoleIt); 
} 

它也可以作爲一個nuget package