我们正在尝试各种方法来限制给定时间段内的用户操作:
- 限制问题/答案帖
- 限制编辑
- 限制提要检索
目前,我们正在使用缓存简单地插入用户活动的记录-如果该记录存在(如果/当用户进行相同活动时),我们将进行限制。
自动使用缓存可为我们提供陈旧的数据清理和滑动用户活动窗口,但如何扩展可能是个问题。
还有什么其他方式可以确保可以有效地限制请求/用户操作(强调稳定性)?
我们正在尝试各种方法来限制给定时间段内的用户操作:
目前,我们正在使用缓存简单地插入用户活动的记录-如果该记录存在(如果/当用户进行相同活动时),我们将进行限制。
自动使用缓存可为我们提供陈旧的数据清理和滑动用户活动窗口,但如何扩展可能是个问题。
还有什么其他方式可以确保可以有效地限制请求/用户操作(强调稳定性)?
Answers:
这是过去一年中我们在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缓存在这里像冠军一样工作-通过使用它,您可以自动清除油门条目。随着流量的增长,我们看不到这是服务器上的问题。
随时提供有关此方法的反馈;当我们使Stack Overflow更好时,您可以更快地获得Ewok的修复功能:)
REMOTE_ADDR
和HTTP_X_FORWARDED_FOR
服务器变量,并进行适当的清理。
Microsoft具有IIS 7的新扩展,称为IIS 7.0的动态IP限制扩展-Beta。
“ IIS 7.0的动态IP限制是一个模块,可提供针对Web服务器和Web站点上的拒绝服务和暴力攻击的防护。通过临时阻止发出并发请求数量异常高的HTTP客户端的IP地址,可以提供这种保护。或在短时间内提出大量要求的人。” http://learn.iis.net/page.aspx/548/using-dynamic-ip-restrictions/
例:
如果将条件设置为“以后阻止”,X requests in Y milliseconds
否则X concurrent connections in Y milliseconds
将阻止IP地址,Y milliseconds
然后将再次允许请求。
<location>
。这是对应用程序的所有请求,或者没有。
我们使用从此URL http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx借用的技术,不是为了节流,而是为了穷人的拒绝服务(DOS)。这也是基于缓存的,可能与您正在执行的操作类似。您是否在节流以防止DOS攻击?当然可以使用路由器来减少DOS。您认为路由器可以处理您需要的限制吗?