Обратное давление в системе: оптимизация и цифры
Когда сервис принимает запросы быстрее, чем успевает их обрабатывать, очередь растёт до таймаутов и 502. Разбираем, как измерить обратное давление, ограничить поток и доказать эффект цифрами.

Сервис, который принимает 1000 запросов в секунду, но обрабатывает только 800, каждую секунду накапливает ещё 200 задач. За минуту очередь вырастет на 12 000 элементов, даже если CPU пока не достиг 100%. Это и есть обратное давление: система ограничивает входной поток, потому что следующий участок конвейера не справляется.
Что именно ломается при избытке нагрузки
Рассмотрим типичный путь запроса: HTTP-балансировщик, приложение, очередь задач, база данных и внешние API. У каждого звена есть собственная пропускная способность. Общую скорость обработки задаёт самое медленное из них.
Если приложение принимает запросы без ограничений, лишняя работа не исчезает. Она превращается в очередь в памяти, соединения к базе, сообщения в брокере или запросы, которые уже ждут таймаута на клиенте.
Проблема усиливается каскадно:
- растёт число активных соединений и потребление памяти;
- пул соединений к PostgreSQL 16 или другой базе заполняется ожидающими запросами;
- увеличивается время ответа, хотя средняя загрузка CPU может оставаться умеренной;
- клиенты повторяют неудачные запросы, добавляя нагрузку;
- после восстановления система получает новый пик из накопившихся повторов.
Обратное давление — это не способ сделать медленный компонент быстрее. Это способ не дать ему утонуть и честно сообщить источнику нагрузки, что скорость нужно снизить.
Очередь1 здесь означает не только RabbitMQ или Kafka. Ею может быть список задач в памяти процесса, пул воркеров, очередь соединений или набор запросов, ожидающих свободного соединения с базой.
Сначала измерьте скорость, а не загрузку CPU
Для диагностики нужны как минимум четыре временных ряда: скорость поступления задач, скорость завершения, длина очереди и возраст самой старой задачи. Одного графика CPU недостаточно: система может тратить время на ожидание базы, сети или блокировок.
Минимальный набор метрик
- Incoming rate — сколько запросов или сообщений приходит в секунду.
- Completion rate — сколько задач успешно завершено в секунду.
- Queue depth — сколько задач ожидает обработки.
- Queue age — сколько ждёт самая старая задача.
- Latency p50, p95 и p99 — медианное и хвостовое время ответа.
- Reject rate — доля отклонённых задач, например с ответом 429 или с переносом в очередь повторов.
- Ошибки downstream — таймауты, исчерпание пула базы, ответы 5xx и ошибки внешних сервисов.
Смотрите на метрики на одном временном диапазоне. Если очередь растёт, incoming rate выше completion rate. Если очередь стабильна, но p99 увеличивается, узкое место может находиться уже внутри обработки.
Как получить цифры до изменений
Запишите базовую линию минимум за один обычный рабочий период и отдельно проведите нагрузочный тест. В отчёте укажите версию приложения, Linux 6.x, PostgreSQL 16.x, размер и тип данных, число экземпляров, лимиты CPU и памяти, параллельность генератора нагрузки и длительность теста.
Не сравнивайте «до» и «после» по разным сценариям. Один прогон должен отвечать на один вопрос: что происходит при фиксированном входном потоке, когда он ниже, равен или выше пропускной способности обработчика.
Три уровня обратного давления
| Уровень | Как ограничивает поток | Цена решения | Когда применять |
|---|---|---|---|
| На входе | Лимит запросов, ограничение числа одновременных соединений, ответ 429 | Часть клиентов получит отказ сразу | Когда работу нельзя безопасно поставить в очередь или важна предсказуемая задержка |
| В очереди | Ограниченная длина очереди, блокировка публикации, временное замедление производителя | Появляется задержка, нужна политика переполнения | Когда задачу можно выполнить позже и есть надёжное хранилище сообщений |
| У потребителя | Ограниченное число сообщений в обработке, небольшой prefetch, контроль пула БД | Ресурсы простаивают при слишком низком лимите | Когда брокер отдаёт сообщений больше, чем приложение и база успевают обработать |
Эти уровни не исключают друг друга. Лимит на HTTP-входе защищает приложение от всплеска, ограниченная очередь защищает память, а лимит параллельных операций защищает базу.
Как считать размер очереди и лимиты
Начните с измерения времени обработки одной задачи. Если один воркер завершает в среднем 40 задач в секунду, а в приложении четыре независимых воркера, теоретический предел равен 160 задачам в секунду. Реальный безопасный предел ниже: часть времени уйдёт на ожидание базы, сетевые повторы и сборку мусора.
Простой расчёт показывает цену дисбаланса. При входящем потоке 1000 задач в секунду и пропускной способности 800 задач в секунду очередь увеличивается на 200 задач в секунду. Буфер в 10 000 задач будет заполнен за 50 секунд. Это математический пример, а не универсальный норматив: ваши значения нужно получить из измерений.
Для оценки задержки полезно применять закон Литтла: среднее число элементов в системе примерно равно произведению средней скорости поступления на среднее время пребывания. Если в обработке и очереди находится 2000 задач при стабильном потоке 100 задач в секунду, среднее пребывание составляет около 20 секунд. При этом p99 может быть намного выше.
Ограничение должно быть конечным. Очередь «без лимита» переносит аварию из приложения в память, диск, брокер или базу. Для каждой очереди заранее задайте:
- максимальную длину или максимальный объём данных;
- время жизни задачи;
- действие при переполнении: отказ, отбрасывание, перенос в отдельное хранилище или пауза производителя;
- метрику и уведомление, которые сработают до полного заполнения;
- способ повторной обработки неуспешных задач без бесконечного цикла.
Оптимизация без маскировки проблемы
Сначала уменьшите работу одной задачи
Проверьте лишние запросы к базе, повторное чтение одинаковых данных, синхронные вызовы внешних сервисов и сериализацию больших объектов. Важно измерять не только среднее время. Если редкие задачи в десять раз тяжелее обычных, именно они могут забить воркеры.
В PostgreSQL 16 смотрите планы запросов и время ожидания, но не увеличивайте пул соединений автоматически. Если база уже упирается в CPU, диск или блокировки, дополнительные соединения создадут больше конкуренции, а не больше пропускной способности.
Затем ограничьте параллелизм
Число воркеров, одновременно выполняющих дорогую операцию, должно соответствовать лимитам downstream. Если один экземпляр приложения может открыть 50 соединений к базе, а запущено 10 экземпляров, теоретический максимум уже составляет 500 соединений. Его нужно сопоставить с лимитом самой базы и с числом других потребителей.
Правильный лимит даёт управляемое ожидание. Слишком большой превращает очередь в скрытый буфер внутри процесса. Слишком маленький снижает пропускную способность и может оставить CPU незагруженным.
Потом выберите поведение при переполнении
Для пользовательского запроса чаще безопаснее вернуть 429 с корректной политикой повторной попытки, чем держать соединение открытым до таймаута. Для платежа или другой невосстанавливаемой операции отбрасывание недопустимо: нужна надёжная запись намерения и идемпотентная обработка.
Для фоновых задач допустима ограниченная очередь, но у неё должен быть срок хранения. Если задача устарела через пять минут, обработка через час только создаст побочные эффекты.
Что измерять после изменения
Сравните одинаковые сценарии по четырём группам показателей:
- стабильность: очередь не растёт бесконечно, нет всплеска OOM и исчерпания соединений;
- скорость: completion rate и фактическая пропускная способность;
- качество сервиса: p95, p99, доля 429 и 5xx;
- цена: CPU, память, количество экземпляров, операции базы и сетевой трафик.
Не объявляйте оптимизацию успешной только потому, что p95 уменьшился. Если вместе с ним выросла доля отброшенных задач, вы не ускорили систему, а перенесли стоимость на клиента. В отчёте должны быть входной поток, объём выполненной работы и объём отклонённых задач.
Где обратное давление ломается
- Повторная отправка без задержки. Клиент получает 429 и немедленно повторяет запрос. Так ограничитель превращается в генератор нового пика. Нужны экспоненциальная задержка, случайная добавка и верхний предел числа попыток.
- Потеря подтверждения. Потребитель завершил работу, но ответ брокеру не дошёл. Повторная доставка возможна, поэтому обработчик должен безопасно переносить повторный запуск.
- Неравномерная стоимость задач. Сто сообщений могут занимать меньше времени, чем одно крупное. Ограничивайте не только количество, но при необходимости и суммарный размер или вычислительный бюджет.
- Очередь в памяти. При перезапуске процесса задачи исчезают, а при росте очереди заканчивается память. Для важных данных нужна внешняя надёжная очередь или постоянное хранилище.
- Многоуровневые лимиты. Балансировщик, приложение, брокер и база могут каждый иметь свой предел. Самый маленький лимит станет реальным потолком, а разные таймауты создадут труднообъяснимые обрывы.
Инвалидация кеша, выбор конкретного брокера и настройка схемы повторов — отдельные темы. Здесь важен принцип: каждый накопитель работы должен иметь владельца, предел и наблюдаемое поведение при переполнении.
Что делать дальше
Сначала добавьте графики incoming rate, completion rate, queue depth, queue age, p99 и ошибок downstream. Затем проведите тест с потоком ниже пропускной способности, на границе и выше неё. После этого задайте конечный лимит очереди и отдельно зафиксируйте, что происходит с задачей при отказе.
Следующий показатель для продакшена — не только длина очереди, но и возраст самой старой задачи. Именно он показывает, сколько реально ждёт пользователь или бизнес-процесс. После каждой настройки проверяйте этот показатель вместе с долей повторов и отказов.
1 Backpressure, или обратное давление — механизм, при котором потребитель ограничивает скорость поступления данных от производителя, чтобы не исчерпать свои ресурсы.
IT-архитектор / SQL-оптимизатор: Поиск N+1, оптимизация запросов, code review, поиск багов.
Спросить за 20 ₽Источники: Reactive Streams — спецификация асинхронных потоков с обратным давлением, RabbitMQ Documentation: Consumer Prefetch
Частые вопросы
Обратное давление — это то же самое, что rate limiting?
Как понять, что очередь уже слишком большая?
Что лучше при переполнении: ждать или возвращать 429?
Поможет ли увеличение числа воркеров?
Как проверить результат оптимизации в продакшене?
Что делать, если задача выполнилась, но подтверждение потерялось?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.