Лучший способ реализации запроса дросселирования в ASP.NET MVC?
-
09-06-2019 - |
Вопрос
Мы экспериментируем с различными способами дросселя пользователя в данный период времени:
- Ограничьте вопросы/ответа
- Ограниченные изменения
- Ограничить поиск корма
В настоящее время мы используем кэш, чтобы просто вставить запись активности пользователя - если эта запись существует, если/когда пользователь выполняет одинаковую деятельность, мы захлопываем.
Использование кэша автоматически дает нам устаревшую очистку данных и окна скольжения пользователей, но то, как он будет масштабироваться, может быть проблемой.
Каковы некоторые другие способы обеспечения того, чтобы запросы/действия пользователя могли быть эффективно подавлены (акцент на стабильности)?
Решение
Вот общая версия того, что мы использовали на переполнении стека в течение прошлого года:
/// <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 работает здесь как чемпион здесь - с помощью его, вы получаете автоматическую очистку ваших записей дроссельной заслонки. И с нашим растущим трафиком мы не видим, что это проблема на сервере.
Не стесняйтесь давать отзывы об этом методе; Когда мы делаем переполнение стека лучше, вы получаете свой Ewok Fix даже быстрее :)
Другие советы
Microsoft имеет новое расширение для IIS 7, называемое Dynamic IP -ограничениям расширением для IIS 7.0 - бета.
«Динамические ограничения IP для IIS 7.0 - это модуль, который обеспечивает защиту от отказа в обслуживании и атак грубого силы на веб -сервере и веб -сайтах. Такая защита обеспечивается временной блокировкой IP -адресов клиентов HTTP, которые делают необычно высокое количество одновременных запросов или кто делает большое количество запросов в течение небольшого периода времени ». 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
Затем запросы будут разрешены снова.
Мы используем технику, заимствованную из этого URL http://www.codeproject.com/kb/aspnet/10aspnetperformance.aspx, не для дросселирования, а для отрицания службы бедного человека (DOS). Это также основано на кэше, и может быть похоже на то, что вы делаете. Вы дросселируйте, чтобы предотвратить атаки DOS? Маршрутизаторы, безусловно, могут быть использованы для уменьшения DOS; Как вы думаете, маршрутизатор может справиться с той дроссельной, которая вам нужна?