측정해야 할 오랜 기간 때문에 인 메모리 구조가 충분하지 않을 것이라고 생각합니다. IIS 재활용은이 경우 문제가 될 수 있습니다. 따라서 DB의 리소스에 대한 사용자 액세스를 기록하고 지난 24 시간 동안 만 100을 허용하는 것이 좋습니다.
한편, 여기에는 누출 버킷 리미터 (leaky bucket limiter) 구현이 있습니다 (이는 상대적으로 중요하지 않은 부분을 제한하는 단기적 제한에 더 유용합니다). .NET 4 동시 콜렉션을 사용하면이 구현에서 다소 무차별 잠금을 향상시킬 수 있습니다.
public class RateLimiter
{
private readonly double numItems;
private readonly double ratePerSecond;
private readonly Dictionary<object, RateInfo> rateTable =
new Dictionary<object, RateInfo>();
private readonly object rateTableLock = new object();
private readonly double timePeriod;
public RateLimiter(double numItems, double timePeriod)
{
this.timePeriod = timePeriod;
this.numItems = numItems;
ratePerSecond = numItems/timePeriod;
}
public double Count
{
get
{
return numItems;
}
}
public double Per
{
get
{
return timePeriod;
}
}
public bool IsPermitted(object key)
{
RateInfo rateInfo;
var permitted = true;
var now = DateTime.UtcNow;
lock (rateTableLock)
{
var expiredKeys =
rateTable
.Where(kvp =>
(now - kvp.Value.LastCheckTime)
> TimeSpan.FromSeconds(timePeriod))
.Select(k => k.Key)
.ToArray();
foreach (var expiredKey in expiredKeys)
{
rateTable.Remove(expiredKey);
}
var dataExists = rateTable.TryGetValue(key,
out rateInfo);
if (dataExists)
{
var timePassedSeconds = (now - rateInfo.LastCheckTime).TotalSeconds;
var newAllowance =
Math.Min(
rateInfo.Allowance
+ timePassedSeconds
* ratePerSecond,
numItems);
if (newAllowance < 1d)
{
permitted = false;
}
else
{
newAllowance -= 1d;
}
rateTable[key] = new RateInfo(now,
newAllowance);
}
else
{
rateTable.Add(key,
new RateInfo(now,
numItems - 1d));
}
}
return permitted;
}
public void Reset(object key)
{
lock (rateTableLock)
{
rateTable.Remove(key);
}
}
private struct RateInfo
{
private readonly double allowance;
private readonly DateTime lastCheckTime;
public RateInfo(DateTime lastCheckTime, double allowance)
{
this.lastCheckTime = lastCheckTime;
this.allowance = allowance;
}
public DateTime LastCheckTime
{
get
{
return lastCheckTime;
}
}
public double Allowance
{
get
{
return allowance;
}
}
}
}
lock 문 외부에서 선언 (및 'now'초기화)을하지 않는 것이 좋습니다. 응용 프로그램에서 발생하기는 어렵지 만, 호출 스레드가'lock' 문에서 오랫동안 차단되면 'IsPermitted' 호출에서 예상 한 것과 다른 결과를 얻을 수 있습니다. –