在 ASP.NET MVC 中实现请求限制的最佳方法? [英] Best way to implement request throttling in ASP.NET MVC?

查看:37
本文介绍了在 ASP.NET MVC 中实现请求限制的最佳方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在尝试各种方法来限制给定时间段内的用户操作:

We're experimenting with various ways to throttle user actions in a given time period:

  • 限制问答帖
  • 限制编辑
  • 限制提要检索

目前,我们使用缓存来简单地插入用户活动的记录 - 如果当/当用户执行相同的活动时该记录存在,我们会进行节流.

For the time being, we're using the Cache to simply insert a record of user activity - if that record exists if/when the user does the same activity, we throttle.

自动使用缓存为我们提供了陈旧的数据清理和用户的滑动活动窗口,但它如何扩展可能是一个问题.

Using the Cache automatically gives us stale data cleaning and sliding activity windows of users, but how it will scale could be a problem.

还有哪些其他方法可以确保可以有效地限制请求/用户操作(强调稳定性)?

What are some other ways of ensuring that requests/user actions can be effectively throttled (emphasis on stability)?

推荐答案

以下是我们过去一年在 Stack Overflow 上使用的通用版本:

Here's a generic version of what we've been using on Stack Overflow for the past year:

/// <summary>
/// Decorates any MVC route that needs to have client requests limited by time.
/// </summary>
/// <remarks>
/// Uses the current System.Web.Caching.Cache to store each client request to the decorated route.
/// </remarks>
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class ThrottleAttribute : ActionFilterAttribute
{
    /// <summary>
    /// A unique name for this Throttle.
    /// </summary>
    /// <remarks>
    /// We'll be inserting a Cache record based on this name and client IP, e.g. "Name-192.168.0.1"
    /// </remarks>
    public string Name { get; set; }

    /// <summary>
    /// The number of seconds clients must wait before executing this decorated route again.
    /// </summary>
    public int Seconds { get; set; }

    /// <summary>
    /// A text message that will be sent to the client upon throttling.  You can include the token {n} to
    /// show this.Seconds in the message, e.g. "Wait {n} seconds before trying again".
    /// </summary>
    public string Message { get; set; }

    public override void OnActionExecuting(ActionExecutingContext c)
    {
        var key = string.Concat(Name, "-", c.HttpContext.Request.UserHostAddress);
        var allowExecute = false;

        if (HttpRuntime.Cache[key] == null)
        {
            HttpRuntime.Cache.Add(key,
                true, // is this the smallest data we can have?
                null, // no dependencies
                DateTime.Now.AddSeconds(Seconds), // absolute expiration
                Cache.NoSlidingExpiration,
                CacheItemPriority.Low,
                null); // no callback

            allowExecute = true;
        }

        if (!allowExecute)
        {
            if (String.IsNullOrEmpty(Message))
                Message = "You may only perform this action every {n} seconds.";

            c.Result = new ContentResult { Content = Message.Replace("{n}", Seconds.ToString()) };
            // see 409 - http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
            c.HttpContext.Response.StatusCode = (int)HttpStatusCode.Conflict;
        }
    }
}

示例用法:

[Throttle(Name="TestThrottle", Message = "You must wait {n} seconds before accessing this url again.", Seconds = 5)]
public ActionResult TestThrottle()
{
    return Content("TestThrottle executed");
}

ASP.NET 缓存在这里就像一个冠军 - 通过使用它,您可以自动清理您的节流条目.随着我们的流量不断增长,我们没有发现这是服务器上的问题.

The ASP.NET Cache works like a champ here - by using it, you get automatic clean-up of your throttle entries. And with our growing traffic, we're not seeing that this is an issue on the server.

请随时对此方法提供反馈;当我们让 Stack Overflow 变得更好时,您的Ewok 修复会更快:)

Feel free to give feedback on this method; when we make Stack Overflow better, you get your Ewok fix even faster :)

这篇关于在 ASP.NET MVC 中实现请求限制的最佳方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆