2013-06-05 3 views
3

Last.fm의 API에 사용할 API 속도 제한기를 작성했습니다.API 속도 제한 기

Last.fm의 Tos는 초당 원래 IP 주소 당 5 개 이상의 요청을 만들 수는 없으며 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

제 의견으로는 꽤 괜찮습니다. 그 외,이 코드에는 버그가 있습니다. 이것은 각 요청이 서로 다음에 1 초 이상 끝나면 어떨까요? 그 블록 안에는 결코 들어가지 않을거야 if. 따라서 어떤 종류의 memory leak_requests이 더 커질 수 있으며, 위의 시나리오가 항상 인 경우 클리어되지 않을 수 있습니다.

예 :

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

당신이 할 수있는 것은 당신의 방법의 끝에 다음 행을 추가하는 등의 1 개 번째 규칙을 초과하는 당신의 _requests의 항목을 제거하는 것입니다.

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로 사용할 수 있습니다.