Регулирование нагрузки на веб-приложение ASP.NET MVC

Бывают ситуации, когда внешние ресурсы обращаются к веб-приложению слишком часто. Это могут быть краулеры или другие роботы. Если это создает проблемы для производительности приложения, то такие запросы можно ограничить. В данной статье я расскажу как это сделать для приложения ASP.NET MVC.

Для того, чтобы ограничить количество запросов, обрабатываемых в единицу времени можно воспользоваться библиотекой MvcThrottle.

Создадим проект и установим пакет из Nuget:

Install-Package MvcThrottle

Как только пакет установлен, можно использовать фильтр ThrottlingFilter для регулирования нагрузки. Зарегистрируем этот фильтр глобально:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
  filters.Add(new ThrottlingFilter
  {
    Policy = new ThrottlePolicy(1, null, null, null, null) { IpThrottling = true }
  });
}

Для того, чтобы включить регулирование нагрузки для контроллера или действия его нужно разметить атрибутом [EnableThrottling].

public class HomeController : Controller
{
  [EnableThrottling]
  public ActionResult Index()
  {
    return View();
  }
}

Этого достаточно, чтобы включить регулирование нагрузки для действия контроллера ASP.NET MVC.

В приведенной выше конфигурации нагрузка ограничивается одним запросом в секунду. Этот параметр можно настраивать более тонко:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
  filters.Add(new ThrottlingFilter
  {
    Policy = new ThrottlePolicy(
          perSecond: 5,
          perHour: 200,
          perDay: 4000) { IpThrottling = true }
  });
}

Кроме того, эту настройку можно выполнить индивидуально для каждого действия или контроллера:

public class HomeController : Controller
{
  [EnableThrottling(PerSecond = 10)]
  public ActionResult Index()
  {
    return View();
  }
}

При превышении доступного значения, приложение отдает ошибку HTTP 429.

При желании можно настроить это поведение:

public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
  filters.Add(new ThrottlingFilter
  {
    Policy = new ThrottlePolicy(
          perSecond: 5,
          perHour: 200,
          perDay: 4000)
    {
          IpThrottling = true
    },
    QuotaExceededResponseCode = HttpStatusCode.Forbidden,
    QuotaExceededMessage = "Try again later"
  });
}

Кроме того, можно настроить:

  • собственное представление ошибки, вместо стандартной страницы IIS;
  • белый список адресов, к которым регулирование не применяется;
  • способ определения конечной точки;
  • логгирование.