Как использовать алгоритмы ограничения скорости в ASP.NET Core

автор vadim


Ограничение скорости — это метод, используемый для ограничения количества запросов, разрешенных к определенному ресурсу в определенное временное окно, для предотвращения DDoS-атак и злоупотреблений API. При достижении порога ограничения скорости последующие запросы к ресурсу запрещаются, задерживаются или регулируются.

В предыдущей статье я рассказал, как начать работу с новым промежуточным программным обеспечением для ограничения скорости в ASP.NET Core 7. В этой статье я рассмотрю четыре различных алгоритма ограничения скорости, доступные в ASP.NET Core 7: фиксированное окно, скользящее окно, ведро маркеров и параллелизм.

Чтобы использовать примеры кода, представленные в этой статье, в вашей системе должна быть установлена ​​Visual Studio 2022. Если у вас еще нет копии, вы можете скачать Visual Studio 2022 здесь.

Создайте минимальный проект веб-API ASP.NET Core в Visual Studio 2022.

Прежде всего, давайте создадим минимальный проект веб-API ASP.NET Core 7 в Visual Studio 2022. Выполните следующие действия:

  1. Запустите интегрированную среду разработки Visual Studio 2022.
  2. Нажмите «Создать новый проект».
  3. В окне «Создать новый проект» выберите «ASP.NET Core Web API» из списка отображаемых шаблонов.
  4. Нажмите “Далее.
  5. В окне «Настроить новый проект» укажите имя и расположение нового проекта.
  6. При желании установите флажок «Поместить решение и проект в один каталог», в зависимости от ваших предпочтений.
  7. Нажмите “Далее.
  8. В следующем окне «Дополнительная информация» выберите «NET 7.0 (Current)» в качестве платформы. Снимите флажок «Использовать контроллеры…», так как в этом примере мы будем использовать минимальные API. Оставьте для параметра «Тип аутентификации» значение «Нет» (по умолчанию).
  9. Убедитесь, что все флажки «Включить Docker», «Настроить для HTTPS» и «Включить поддержку Open API» сняты. Мы не будем использовать ни одну из этих функций здесь.
  10. Щелкните Создать.

Мы будем использовать этот проект веб-API ASP.NET Core 7 для создания минимального API и реализации четырех различных алгоритмов ограничения скорости в следующих разделах.

Реализовать контроллер в ASP.NET Core 7.

Давайте реализуем контроллер, чтобы продемонстрировать, как работает ограничение скорости в ASP.NET Core. Для этого выберите папку решения Controllers вашего проекта и нажмите Add -> Controller. Выберите шаблон «Контроллер API — пустой» из списка шаблонов, отображаемых в окне «Добавить шаблон», и введите имя. для контроллера при появлении запроса. Затем замените код по умолчанию следующим.

    [Route("api/[controller]")]
    [ApiController]
    public class DefaultController : ControllerBase
    {
        [HttpGet]
        public string Get()
        {
            return "Hello World";
        }
        [HttpGet("{id}")]
        public string Get(int id)
        {
            return $"The value of id is: {id}";
        }
    }

Абстрактный базовый класс RateLimiter в ASP.NET Core 7.

До ASP.NET Core 7 ограничение скорости было доступно как часть пространства имен Microsoft.AspNetCore.RateLimiting. Ограничение скорости в ASP.NET Core 7 теперь доступно как часть пространства имен System.Threading.RateLimiting.

Основным типом является абстрактный базовый класс RateLimiter, обладающий несколькими замечательными свойствами. Абстрактный класс RateLimiter выглядит следующим образом:

public abstract class RateLimiter : IAsyncDisposable, IDisposable
{
    public abstract RateLimiterStatistics? GetStatistics();
    public abstract TimeSpan? IdleDuration { get; }
    public RateLimitLease AttemptAcquire(int permitCount = 1);
    protected abstract RateLimitLease AttemptAcquireCore(int permitCount);
    public ValueTask<RateLimitLease> AcquireAsync(int permitCount = 1, CancellationToken cancellationToken = default);
    protected abstract ValueTask<RateLimitLease> AcquireAsyncCore(int permitCount, CancellationToken cancellationToken);
    protected virtual void Dispose(bool disposing);
    public void Dispose();
    protected virtual ValueTask DisposeAsyncCore();
    public async ValueTask DisposeAsync();
}

Обратите внимание, что здесь представлены только объявления методов. Определения методов опущены для краткости.

Настройка ограничения скорости в ASP.NET Core 7

Чтобы настроить ПО промежуточного слоя для ограничения скорости в ASP.NET Core 7, вы используете метод AddRateLimiter. Чтобы добавить ПО промежуточного слоя для ограничения скорости в приложение ASP.NET Core 7, вы сначала добавляете необходимые службы в контейнер, как показано во фрагменте кода, приведенном ниже.

builder.Services.AddRateLimiter(options =>{    //Write your code to configure the middleware here});

Чтобы добавить ПО промежуточного слоя в конвейер, вы вызываете метод расширения UseRateLimiter, как показано ниже.

app.UseRateLimiter(); 

Вы можете настроить RateLimiter с несколькими параметрами, включая максимально допустимое количество запросов, код состояния ответа и временное окно. Вы также можете определить ограничение скорости на основе метода HTTP, IP-адреса клиента и других факторов. Кроме того, вы можете ставить запросы в очередь вместо того, чтобы отклонять их.

Алгоритмы ограничения скорости в ASP.NET Core 7

Пакет System.Threading.RateLimiting обеспечивает поддержку следующих алгоритмических моделей:

  • Фиксированное окно
  • Раздвижное окно
  • Сегмент токенов
  • параллелизм

Фиксированное окно

Алгоритм фиксированного окна допускает фиксированное количество запросов в течение определенного временного окна, а все последующие запросы регулируются. Основываясь на требовании ограничения скорости, этот алгоритм делит время на фиксированные окна. Например, предположим, что вы хотите разрешить 10 запросов в минуту. Как только этот предел будет достигнут, последующие запросы будут отклонены до сброса окна.

В следующем фрагменте кода показано, как можно настроить ограничитель фиксированной скорости окна в файле Program.cs в ASP.NET Core 7.

builder.Services.AddRateLimiter(options => {
    options.RejectionStatusCode = 429;
    options.AddFixedWindowLimiter(policyName: "fixed", options => {
        options.PermitLimit = 3;
        options.Window = TimeSpan.FromSeconds(10);
        options.AutoReplenishment = true;
        options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        options.QueueLimit = 2;
    });
});

Метод AddLimiter используется для добавления служб ограничения скорости в контейнер служб. Метод AddFixedWindowLimiter используется для добавления политики фиксированного окна. Имя политики указано здесь как «фиксированное». Обратите внимание на значения свойств PermitLimit и Window. Установив PermitLimit на 3 и Window на 10, вы разрешаете максимум три запроса каждые 10 секунд.

Когда вы запускаете приложение и вызываете конечную точку чаще, чем допустимое ограничение, по умолчанию будет возвращен код состояния HTTP 503 «Служба недоступна». Просто измените RejectionStatusCode, чтобы он возвращал другой код состояния. В приведенном выше примере свойство RejectionStatusCode настроено на возврат кода состояния HTTP 429 «Слишком много запросов».

Кроме того, QueueProcessingOrder указывается как OldestFirst, а QueueLimit имеет значение 2. Таким образом, последующие два запроса будут регулироваться и сохраняться в очереди всякий раз, когда будет превышено ограничение окна. Затем самый старый запрос будет выбран из очереди и обработан.

Раздвижное окно

Подобно фиксированному окну, алгоритм скользящего окна допускает фиксированное количество запросов за временное окно. Разница в том, что скользящее окно делит временное окно на сегменты. На каждом интервале сегмента окно сдвигается на один сегмент.

Интервал сегмента равен времени окна, деленному на количество сегментов в окне. Итак, если ваше окно составляет 60 секунд, и вы указываете два сегмента, временное окно будет сдвигаться каждые 30 секунд.

В следующем фрагменте кода показано, как можно настроить ограничитель скорости скользящего окна в файле Program.cs в ASP.NET Core 7.

builder.Services.AddRateLimiter(options => {
    options.RejectionStatusCode = 429;
    options.AddSlidingWindowLimiter(policyName: "sliding", options => {
        options.PermitLimit = 30;
        options.Window = TimeSpan.FromSeconds(60);
        options.SegmentsPerWindow = 2;
        options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        options.QueueLimit = 2;
    });
});

Свойство SegmentsPerWindow используется для указания количества сегментов во временном окне.

Сегмент токенов

В алгоритме корзины токенов каждый токен в корзине представляет собой запрос. Маркер удаляется из корзины всякий раз, когда обслуживается запрос. Если ведро становится пустым, следующий запрос отклоняется или регулируется. Со временем ведро наполняется с фиксированной скоростью.

Рассмотрим пример, когда ведро имеет ограничение в 10 токенов. Когда приходит запрос и доступен токен, запрос будет обслуживаться, а количество токенов уменьшается. Если лимит токенов превышен, а токенов не осталось, запросы будут отклонены или ограничены.

В следующем примере кода показано, как настроить ограничитель скорости токена в файле Program.cs в ASP.NET Core 7.

builder.Services.AddRateLimiter(options => {
    options.RejectionStatusCode = 429;
    options.AddTokenBucketLimiter(policyName: "token", options => {
        options.TokenLimit = 2;
        options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        options.QueueLimit = 2;
        options.ReplenishmentPeriod = TimeSpan.FromSeconds(10);
        options.TokensPerPeriod = 2;
        options.AutoReplenishment = true;
    });
});

Свойство TokenLimit указывает максимальное количество токенов, которое может храниться в корзине в любой момент времени.

параллелизм

Ограничитель параллелизма контролирует максимальное количество одновременных запросов к ресурсу. Если вы установите ограничение, например, 10, только первым 10 запросам будет предоставлен доступ к ресурсу в данный момент времени. Всякий раз, когда запрос завершается, он открывает слот для нового запроса.

В следующем фрагменте кода показано, как настроить ограничитель скорости параллелизма в ASP.NET Core 7.

builder.Services.AddRateLimiter(options => {
    options.RejectionStatusCode = 429;
    options.AddConcurrencyLimiter(policyName: "concurrency", options => {
        options.PermitLimit = 3;
        options.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;
        options.QueueLimit = 2;
    });
});

Включить или отключить ограничение скорости в ASP.NET Core 7

Вы можете применить ограничение скорости к контроллеру, методу действия или странице Razor. [EnableRateLimiting] и [DisableRateLimiting] Атрибуты можно использовать для включения или отключения ограничения скорости в ASP.NET Core 7.

В следующем листинге кода показано, как можно применить «фиксированный» ограничитель скорости к DefaultController, который мы создали ранее, и отключить ограничение скорости в методе действия того же контроллера.

    [Route("api/[controller]")]
    [ApiController]
    [EnableRateLimiting("fixed")]
    public class DefaultController : ControllerBase
    {
        [HttpGet]
        public string Get()
        {
            return "Hello World";
        }
        [HttpGet("{id}")]
        [DisableRateLimiting]
        public string Get(int id)
        {
            return $"The value of id is: {id}";
        }
    }

Ограничение скорости имеет ряд преимуществ. Он может защитить ваши приложения или API-интерфейсы от отказа в обслуживании и других злонамеренных атак, а также от незлонамеренного чрезмерного использования. Уменьшая объем запросов в определенное временное окно и, таким образом, сокращая сетевой трафик и снижая затраты на инфраструктуру. Наконец, это может даже повысить производительность вашего приложения, обеспечив справедливое использование доступных ресурсов.

В следующей статье на эту тему я расскажу, как мы можем реализовать пользовательские политики ограничения скорости в ASP.NET Core 7.

Related Posts

Оставить комментарий