3
我見過賈羅德·狄克遜的實現來電每秒的速率限制溶液(Best way to implement request throttling in ASP.NET MVC?)。我現在試圖弄清楚如何爲每日N次呼叫建立一個類似的過濾器。通話每一天率ASP.NET MVC 3限制?
我建立一個開發者的API,其中免費賬戶每天能獲得100〜電話和付費賬戶獲得更高的速率限制。在MVC 3中進行每日呼叫速率限制的最佳方式是什麼?
我見過賈羅德·狄克遜的實現來電每秒的速率限制溶液(Best way to implement request throttling in ASP.NET MVC?)。我現在試圖弄清楚如何爲每日N次呼叫建立一個類似的過濾器。通話每一天率ASP.NET MVC 3限制?
我建立一個開發者的API,其中免費賬戶每天能獲得100〜電話和付費賬戶獲得更高的速率限制。在MVC 3中進行每日呼叫速率限制的最佳方式是什麼?
我不認爲在內存中的結構就足夠了這裏,因爲你需要測量時間長。在這種情況下,IIS回收會有問題。因此,我建議記錄用戶對數據庫資源的訪問權限,並且只允許在過去24小時內計數100。
在另一方面,這裏是我們實現一個漏桶限幅(這是短期的限制,其中失敗是相對不重要更加得心應手)的。使用.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'叫什麼得到不同的結果。 – 2012-12-17 14:28:28