Load Shedding pattern: adaptive admission control, priority-based rejection, deadline-aware shedding. Compares unbounded queue meltdown vs graceful degradation under 10x traffic spike.
Load shedding отвечает на неприятный, но неизбежный вопрос: что система должна сделать, когда входящего трафика больше, чем она может обработать. Интуитивный ответ «положим в очередь и подождем» часто разрушает production. Очередь растет, latency растет, клиенты упираются в timeout, начинают retry, эти retry добавляют еще больше работы, память уходит в буфер, downstream базы и кэши получают лавину соединений. В итоге система не просто обслуживает медленно, а перестает обслуживать всех.
Load shedding выбирает контролируемый отказ вместо неконтролируемого обвала. Он заранее отбрасывает часть запросов, чтобы оставшаяся часть продолжала получать нормальную задержку. Это SRE-паттерн, который защищает SLO и снижает blast radius: лучше честный 503 Retry-After для части клиентов, чем минутный incident для всей функции. Связанные темы: timeout-deadline, back-pressure, circuit-breaker, rate-limiting, priority-queue.
Представьте вход в станцию метро при перегрузке. Если открыть все турникеты без контроля, платформа переполнится, поезда не смогут нормально выгружать людей, и станция встанет. Admission control ограничивает вход раньше, чем перегруженный участок станет опасным. Пользователь снаружи недоволен, но система внутри продолжает работать.
В сервисной архитектуре load shedding является входным клапаном. Он смотрит на CPU, очередь, deadline, тип пользователя, критичность операции и решает: принять работу, вернуть быстрый отказ, отдать degraded result или попросить клиента повторить позже. Главное: отказ должен быть ранним и дешевым. Если запрос уже занял connection pool, захватил DB transaction и только потом был отменен, shedding почти не помог.
Диаграмма показывает клиентов с резким всплеском до 10K req/s, load balancer с admission control, bounded admission queue, несколько app-инстансов и Postgres. Топология намеренно проста: проблема не в необычной схеме, а в поведении под overload. Один и тот же cluster может уйти в cascading failure или пережить всплеск в зависимости от политики на входе.
В первом сценарии LB принимает все, очередь раздувается, app-инстансы ждут и создают давление на базу. Затем появляются timeout и retry storm. Во втором сценарии LB измеряет состояние и отбрасывает часть трафика, когда CPU выше порога. Принятые запросы идут с нормальной задержкой, отклоненные получают понятный ответ и Retry-After. Третий сценарий добавляет business priority: paid и critical операции принимаются, free tier деградирует. Четвертый сценарий показывает deadline-aware подход: если запрос уже не успеет до дедлайна, система не тратит на него ресурсы.
no-shedding-meltdown учит, что unbounded queue не является надежностью. Она скрывает проблему до тех пор, пока задержка не станет больше клиентского timeout. После этого каждый ожидающий запрос превращается в дубликаты, а очередь становится усилителем нагрузки. ADR-вывод: очередь должна иметь размер, метрики и политику отказа; бесконечная очередь запрещена для online path.
adaptive-shedding показывает admission control по сигналам перегрузки. CPU 85%, queue depth, active requests, event loop lag и saturation connection pool могут быть триггерами. ADR-вывод: shedding лучше делать на edge/API gateway, где запрос еще дешевый. Порог должен быть проверен load test'ом, а не выбран из воздуха.
priority-shedding учит, что случайный drop не всегда приемлем. Во время перегрузки бизнес может предпочесть сохранить платежи, логин, безопасность и платных пользователей, временно ухудшив analytics, search suggestions или free tier. ADR-вывод: у запросов должна быть классификация critical/high/normal/low, а политика shedding должна быть согласована с product и support.
deadline-aware показывает, что запросы с коротким оставшимся бюджетом часто бессмысленны. Если текущий wait time 90 ms, а операция занимает минимум 50 ms, запрос с deadline через 100 ms уже проигран. ADR-вывод: deadline должен передаваться через сервисы, а не теряться после первого hop. Это связывает load shedding с timeout-deadline.
Первый trade-off: availability для всех против latency для части. Без shedding можно попытаться принять 100% запросов, но p99 вырастет и фактическая успешность упадет. С shedding часть запросов получает отказ, зато принятая часть укладывается в SLO. Для интерактивных систем это часто правильнее.
Второй trade-off: простая rate-based политика против adaptive. Фиксированный лимит RPS легко объяснить, но он не учитывает, что запросы бывают разной стоимости и инфраструктура меняет емкость. Adaptive shedding сложнее отлаживать, зато реагирует на реальные признаки saturation.
Третий trade-off: priority-based защита против fairness. Если всегда защищать paid tier, free пользователи могут страдать долго. Если делать строго равномерно, можно потерять revenue path. ADR-подход: зафиксировать минимальную долю capacity для низких приоритетов или явно объявить degraded mode.
Четвертый trade-off: быстрый reject против клиентских retry. 503 без Retry-After, backoff и jitter превращается в retry storm. Поэтому shedding не существует отдельно от client behavior. Сервер должен возвращать семантически правильный код, а клиенты должны уважать backoff.
Google SRE описывает overload handling как обязательную часть надежности: сервис должен уметь сказать «нет» до того, как он потеряет способность говорить вообще. Envoy поддерживает circuit breakers, outlier detection и overload manager. Netflix Concurrency Limits использует adaptive limits по сигналам latency. AWS API Gateway и многие edge-прокси умеют throttling и quota. Kubernetes admission control защищает control plane и scheduler от неконтролируемого потока объектов.
В приложениях похожие практики выглядят как bounded executor queues, max in-flight requests, semaphore isolation, token buckets, bulkheads и graceful degradation. Для payment path можно принять меньше фоновой работы; для social feed можно вернуть cached/stale данные; для search можно отключить дорогие facets.
Главная ошибка: «добавим очередь побольше». Большая очередь повышает latency и память, но не добавляет CPU и DB capacity. Вторая ошибка: shedding после того, как queue уже 100K. Это поздно: запросы уже удерживают ресурсы, клиенты уже ретраят. Третья ошибка: случайно отбрасывать critical и low-value запросы одинаково. Четвертая: возвращать 500 вместо 503/429, лишая клиента понимания, что это overload, а не bug.
Еще одна типичная проблема: отсутствие тестов. Политика shedding, которую ни разу не проверяли под нагрузкой, может сработать слишком рано или слишком поздно. Нужны load tests, fault injection и dashboards: admitted RPS, rejected RPS, queue depth, p99, retry rate, CPU, DB connections.
Load shedding не заменяет capacity planning. Если сервис всегда живет на 95% CPU, отбрасывание запросов лишь маскирует недокупленную емкость. Не стоит shedding'ом закрывать баги с медленными SQL-запросами, утечками памяти или отсутствием индексов. Не нужен сложный adaptive алгоритм для offline batch pipeline, где задержка допустима, а важнее eventual completion. Не надо отбрасывать операции, которые нельзя безопасно повторить, пока нет идемпотентности и понятного клиентского контракта.
В CloudArch продолжайте с timeout-deadline, back-pressure, circuit-breaker, rate-limiting, priority-queue, bulkhead, api-gateway и payment-system. Из внешнего: Google SRE Book, глава Handling Overload; статьи Marc Brooker про очереди и latency; Envoy overload manager; Netflix Concurrency Limits; материалы по exponential backoff с jitter.