2008-08-29 10 views
194

Estamos experimentando con distintas formas a las acciones del usuario del acelerador en un determinado período de tiempo :¿La mejor manera de implementar la aceleración de solicitudes en ASP.NET MVC?

  • límite mensajes de preguntas/respuestas
  • límite edita
  • recuperaciones de alimentación Límite

Para de momento, estamos usando el Caché para simplemente insertar un registro de la actividad del usuario; si ese registro existe si/cuando el usuario hace la misma actividad, aceleramos.

El uso de la memoria caché nos da automáticamente la limpieza de datos obsoletos y el deslizamiento de las ventanas de actividad de los usuarios, pero cómo se puede escalar podría ser un problema.

¿Cuáles son algunas otras formas de garantizar que las solicitudes/acciones del usuario se puedan reducir con eficacia (énfasis en la estabilidad)?

+0

¿Estás intentando limitar por usuario o por pregunta? Si por usuario, podría usar sesión, que sería un conjunto más pequeño. –

+1

Es por usuario, pero no pudimos usar la Sesión, ya que eso requiere cookies; estamos limitando en función de la dirección IP actualmente. –

Respuesta

217

Aquí hay una versión genérica de lo que hemos estado usando el desbordamiento de la pila durante el último año: el uso

/// <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; 
     } 
    } 
} 

muestra:

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

El caché de ASP.NET funciona como un campeón aquí - al usarlo, obtiene una limpieza automática de las entradas de su acelerador. Y con nuestro creciente tráfico, no estamos viendo que esto sea un problema en el servidor.

Siéntase libre de dar su opinión sobre este método; cuando mejoramos Stack Overflow, obtienes tu Ewok fix aún más rápido :)

+4

pregunta rápida: está utilizando el valor c.HttpContext.Request.UserHostAddress como parte de la clave. ¿Es posible que ese valor sea vacío o nulo o tenga el mismo valor? (es decir, si está utilizando un equilibrador de carga y es la dirección IP de esa máquina ... no los clientes reales) Como, ¿los equilibradores de carga o de proxy (es decir, un BIG IP F5) colocan los mismos datos allí y necesita verificar para X-Forwarded-For también o algo así? –

+6

@ Pure.Krome - sí, podría ser. Al recuperar la dirección IP del cliente, usamos una función auxiliar que verifica las variables del servidor 'REMOTE_ADDR' y' HTTP_X_FORWARDED_FOR' y las desinfecta adecuadamente. –

+2

Pero esto no funcionaría en una granja web, ¿o sí? Dado que ¿cómo puede funcionar con Stack Overflow? ¿No necesita algún tipo de caché compartida, como con Windows Server AppFabric o memcached? – BrettRobi

9

Utilizamos la técnica prestada de esta URL http://www.codeproject.com/KB/aspnet/10ASPNetPerformance.aspx, no para la regulación, sino para la denegación de servicio de un hombre pobre (D.O.S). Esto también está basado en caché, y puede ser similar a lo que está haciendo. ¿Está estrangulando para evitar D.O.S. ataques? Los enrutadores sin duda se pueden utilizar para reducir D.O.S; ¿Crees que un enrutador podría manejar la aceleración que necesitas?

+1

Eso es más o menos lo que ya estamos haciendo, pero funciona muy bien :) –

67

Microsoft tiene una nueva extensión para IIS 7 llamada Dynamic IP Restrictions Extension para IIS 7.0 - Beta.

"Las restricciones de IP dinámica para IIS 7.0 es un módulo que proporciona protección contra la denegación de servicio y la fuerza bruta ataques a servidores web y sitios web. Dicha protección es proporcionada por el bloqueo temporal de las direcciones IP de los clientes HTTP que hacen un número inusualmente alto de solicitudes concurrentes o que hacen una gran cantidad de solicitudes durante un período de tiempo pequeño ". http://learn.iis.net/page.aspx/548/using-dynamic-ip-restrictions/

Ejemplo:

Si establece los criterios para bloquear o después X requests in Y millisecondsX concurrent connections in Y milliseconds la dirección IP será bloqueada durante Y milliseconds continuación, las solicitudes serán permitidos de nuevo.

+1

¿Sabes si causó problemas con rastreadores como el robot de Google? – Helephant

+0

@Helephant http://webmasters.stackexchange.com/questions/26553/iis-dynamic-ip-restrictions-module-and-googlebot – Adrian

+1

Ahora se lanzó y se incluye con IIS a partir de la versión 8 - http: //www.iis .net/learn/get-started/whats-new-in-iis-8/iis-80-dynamic-ip-address-restrictions –

Cuestiones relacionadas