АрхитектураНадёжность и производительностьИнженер по надёжности платформы (SRE)

Как ограничение числа одновременно обрабатываемых запросов предотвращает каскадное ухудшение сервиса?

Как ограничение числа одновременно обрабатываемых запросов предотвращает каскадное ухудшение сервиса?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

Ограничение конкурирующих запросов защищает сервис от исчерпания CPU, памяти, пулов соединений и других конечных ресурсов. Когда лимит достигнут, новые запросы не должны бесконечно ждать: их быстро отклоняют или переводят на контролируемый упрощённый путь. Это сохраняет приемлемое время ответа для уже принятых запросов и предотвращает переход перегрузки в каскадный отказ.

Исторический контекст

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

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

Постановка проблемы

Предположим, что запрос в среднем требует фиксированный объём вычислений, но входной поток временно превышает способность системы. Если принимать все запросы, они начнут ждать в очередях, удерживать память, соединения и рабочие контексты.

Рост очереди увеличивает время ответа. Из-за таймаутов клиентские или промежуточные компоненты могут считать запросы неуспешными, хотя сервер продолжает выполнять их работу. В итоге полезная пропускная способность снижается, а отказ одной зависимости способен распространиться на вызывающие сервисы.

Подробное решение

Сервис задаёт лимит на число запросов, находящихся в критической секции: например, выполняющих обращение к базе данных или внешнему сервису. Пока слот доступен, запрос принимается; при достижении лимита новый запрос быстро получает контролируемый отказ, ответ из кэша или упрощённый результат — в зависимости от контракта.

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

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

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

Ограничение конкуренции дополняют таймаутами и отменой работы, которая больше не нужна вызывающей стороне. Иначе запрос может занимать слот после того, как клиент уже перестал ждать. Метрики должны разделять принятые, отклонённые и завершённые запросы, а также показывать занятость лимита и время ожидания.

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

Ситуация из практики

Сервис оформления заказа обращается к платёжной системе. Во время сбоя платёжная зависимость отвечает медленно, и входящие запросы начинают накапливаться. Были рассмотрены три варианта.

Первый вариант — увеличить число рабочих потоков. Он временно повышает число одновременно выполняемых запросов, но быстро расходует соединения и память, а задержка платёжной системы остаётся прежней. Второй вариант — принимать запросы в неограниченную очередь. Это сохраняет формальную приёмку трафика, но создаёт длинные ожидания и увеличивает вероятность таймаутов.

Третий вариант — установить отдельный лимит одновременных платёжных операций, короткий таймаут и быстрый контролируемый отказ для новых запросов. Был выбран третий вариант: он ограничивает воздействие неисправной зависимости и оставляет ресурсы для просмотра статуса заказа, повторной попытки через пользовательский интерфейс и обработки уже начатых операций.

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

Что кандидаты часто упускают

  1. Чем ограничение конкуренции отличается от ограничения скорости запросов?

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

  1. Почему один глобальный лимит может ухудшить надёжность?

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

  1. Почему увеличение лимита иногда повышает, а не снижает задержку?

Больший лимит позволяет принять больше работы, но после насыщения общего ресурса дополнительные запросы начинают конкурировать за CPU, память, соединения или внешнюю зависимость. Очереди перемещаются внутрь системы, а не исчезают. Поэтому лимит выбирают по точке, где полезная пропускная способность ещё растёт, а задержка и доля ошибок остаются совместимыми с SLO.