TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.74K subscribers
Post #3201 1.68K
День 2673. #ЗаметкиНаПолях
Как Масштабировать Длительные Запросы API
В каждой системе рано или поздно возникает конечная точка, выполнение которой занимает минуты (или даже больше). В итоге пользователи несколько минут ждут ответа, а API удерживает запрос открытым всё это время, расходуя поток, соединение и прочие ресурсы. Небольшой всплеск трафика на этой одной конечной точке потенциально может привести к сбою всего API. Рассмотрим последовательность действий для решения этой проблемы.

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

1. Принимаем работу, но не выполняем её
Добавим таблицу заданий для работы, которую нужно выполнить. Теперь API:
- Проверяет запрос.
- Вставляет строку в таблицу заданий со статусом «Ожидание».
- Возвращает 202 Accepted с ID задания.
Фоновый обработчик внутри того же API, читает строки со статусом «Ожидание» и обрабатывает их. Клиент либо опрашивает конечную точку GET /jobs/{id}, либо — что лучше — сервер отправляет обновления через SignalR, Server-Sent Events или email, когда задание выполнено.
Это уже даёт много преимуществ. Конечная точка быстро возвращает результат, а всплеск входящих запросов просто превращается во всплеск строк в таблице. Запись в таблицу обходится дёшево.

2. Отделение обработчика от API
Фоновый обработчик из шага 1 по-прежнему конкурирует с API за процессор, память и пул соединений. Если обработка становится ресурсоёмкой или медленной, API начинает это ощущать. Решение в том, чтобы вынести фоновый обработчик в отдельно развёртываемый компонент и разместить между ними очередь.
API публикует сообщение в очередь. Пул фоновых обработчиков получает данные из очереди и выполняет фактическую работу.
- Очередь поглощает пиковые нагрузки. API может продолжать принимать задачи с постоянной скоростью, в то время как рабочие процессы выполняют задания в своём темпе.
- Вы масштабируете рабочие процессы отдельно от API. Рост числа фоновых задач не требует увеличения количества экземпляров API.
- Сбой рабочего процесса — просто сообщение, которое возвращается в очередь, а не ошибка 500 для пользователя.
Вы также получаете возможность повторных попыток, приостановку/возобновление, структурированную обработку ошибок и очередь недоставленных сообщений — фактически бесплатно, поскольку инфраструктура очередей уже предоставляет их.

Чего это стоит
Это дополнительные компоненты, которые нужно развёртывать и отслеживать. Теперь клиент должен спрашивать, готов ли ответ, или вы должны его оповещать. И каждая задача должна быть идемпотентной, потому что доставка «хотя-бы-раз» означает, что рабочие процессы будут видеть дубликаты.
Если у вас только одна медленная конечная точка и умеренный трафик, это избыточно. Простое «запустить и забыть» с опросом статуса внутри того же процесса вполне подойдет.

Облачный сервис
Не обязательно делать всё самому. Вот несколько альтернатив:
- AWS SQS + Lambda или Azure Service Bus + Azure Functions, когда нужно масштабировать пул рабочих процессов до нуля и не охота управлять хостами.
- Azure Durable Functions или AWS Step Functions - для многоэтапных рабочих процессов с таймерами, повторными попытками и подтверждением человека. Оркестрация - их сильная сторона.
- Temporal — когда рабочий процесс длится долго (часы, дни), и необходимо первоклассное стабильное выполнение, версионирование и прозрачность между запусками.
Компромисс, как обычно, заключается в меньшем объёме операционной работы, но большей зависимости от поставщика и ценообразовании, которое необходимо тщательно оценить при росте нагрузки.

Источник:
https://www.milanjovanovic.tech/blog/how-to-scale-long-running-api-requests
  • 👍 4
  • 👎 2
More from @netdeveloperdiary
  1. Sep 26, 2026День 2796. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Продолжение Начало Три…
  2. Sep 25, 2026День 2795. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Начало Проблема с позиц…
  3. Sep 24, 2026День 2794. #Оффтоп #Здоровье Сегодня будет необычный пост. Завтра в Москве стартует конфер…
  4. Sep 23, 2026День 2793. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
  5. Sep 22, 2026День 2792. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
  6. Sep 21, 2026🔍Тестовое собеседование с Senior C# разработчиком уже завтра 22 сентября(уже завтра!) в 1…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →