我们正在尝试在给定时间段内 限制用户操作的各种方法:
目前,我们使用缓存来简单地插入用户活动的记录——如果该记录存在,如果/当用户执行相同的活动时,我们会限制。
使用缓存会自动为我们提供陈旧的数据清理和滑动用户活动窗口,但如何扩展可能是一个问题。
还有哪些其他方法可以确保可以有效地限制请求/用户操作(强调稳定性)?
这是我们过去一年在 Stack Overflow 上使用的通用版本:
/// <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 缓存在这里就像一个冠军 - 通过使用它,您可以自动清理您的节流条目。随着我们的流量不断增长,我们没有看到这是服务器上的问题。