asp.net-mvc-3 - ASP.NET MVC 3 中的每日调用速率限制?

标签 asp.net-mvc-3 rate-limiting

我看过 Jarrod Dixon 的解决方案 ( Best way to implement request throttling in ASP.NET MVC? ) 以实现每秒调用速率限制。我现在正试图弄清楚如何为每天 N 次调用构建一个类似的过滤器。

我正在构建一个开发者 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;
            }
        }
    }

}

关于asp.net-mvc-3 - ASP.NET MVC 3 中的每日调用速率限制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5629547/

相关文章:

java - 动态速率限制器以避免数据库限制

Azure API 管理入站规则从基础继承

javascript - 限制 JavaScript 函数调用,但要排队(不要丢弃调用)

asp.net-mvc - 在IIS 7.5上托管的ASP.Net MVC 3/4默认处理程序映射

c# - 枚举标志的模型绑定(bind)列表

laravel - 如何设置 Laravel 每天的速率限制器?

python - Twitter API - 获取关注者的关注者数量

css - 使用 Razor 将 CSS 转换为样式元素

asp.net-mvc - 如何在带有 razor 的 MVC 3 中使用正则表达式

asp.net-mvc-3 - 从 DataTable 填充 MVC Webgrid