Ваша LLM стримит в никуда: разбираемся, как работать с дисконнектами в FastAPI

В FastAPI клиентский дисконнект по умолчанию не останавливает выполнение обработчика, поэтому стриминг от большой языковой модели (LLM) может продолжаться «в пустоту». Главный итог: отключение нужно учитывать явно, иначе страдают ресурсы и корректность работы с БД.

  • По умолчанию разрыв соединения не прерывает пользовательский код: для обычных эндпоинтов событие http.disconnect игнорируется.
  • Для стриминга (StreamingResponse, EventSourceResponse) отключение ловится, но отмена может прервать транзакцию или код очистки.
  • В одном кейсе транзакции оставались открытыми до 40 минут (idle in transaction), после чего появились алерты о «мёртвых» соединениях в пуле.
  • Пример с нестриминговым эндпоинтом: были согласованы лимит параллельности 32 запроса и таймаут 30 секунд, но из-за бага у клиента таймаут стал 10 секунд и начались повторы.
  • В примерах используются версии: Uvicorn 0.40.0, Starlette 0.50.0, FastAPI 0.128.0, vLLM v0.13.0.
  • Нюанс ASGI: требование бросать OSError при send() появилось в ASGI 2.4, а Uvicorn 0.40.0 реализует 2.3 и при disconnected просто отбрасывает данные.

Почему это важно: В сервисах со стримингом ответов от LLM дисконнект клиента может привести к тому, что GPU продолжит генерировать токены, занимая ресурсы self-hosted моделей или накапливая расходы у внешних провайдеров. Ещё заметнее риск для базы данных: транзакции могут остаться незавершёнными, а в пул возвращаются соединения в невалидном состоянии. Без явной обработки теряется статистика незавершённых запросов, что мешает отладке и аналитике.

На что обратить внимание: В статье подчёркивается, что 100% гарантии обнаружения дисконнекта в рамках одного HTTP-запроса недостижимы, поэтому важен баланс между корректностью критичных фаз и возможностью прерывать долгие. Для нестриминговых ответов признак отключения появляется только при явном опросе request.receive() и проверке http.disconnect; метод Request.is_disconnected() описан как ненадёжный при BaseHTTPMiddleware. В стриминге ключевой сигнал — CancelledError, а риск связан с двумя конкурирующими путями завершения (например, ручной break плюс отмена таски фреймворком), из-за чего может пропускаться логика очистки.

Читайте также

  1. Как устроена архитектура факторов ранжирования в рантайме поиска Ozon
  2. Снижение затрат на LLM API через децентрализованную инференс-сеть: практический опыт
  3. Позови оператора
  4. Как я пытался сжимать смыслы вместо байтов
  5. MVVM для курильщика: почему ваша ViewModel — это помойка на 2000 строк и как это исправить
Ключевые инсайты из новости (по версии ChatGPT)
  • FastAPI: обычные эндпоинты не реагируют на client disconnect: В FastAPI/Starlette для нестриминговых ответов (Response/JSONResponse) событие http.disconnect само по себе не останавливает выполнение обработчика: код продолжает работать, даже если клиент уже закрыл соединение. Это важно учитывать в длительных операциях (CPU/GPU/внешние вызовы), иначе сервис тратит ресурсы на запросы, результат которых уже некому доставлять.
    [Backend / FastAPI / Надёжность]
Для получения полного доступа оформите подписку PubMag PRO.
Зарегистрированные пользователи видят только два тезиса.
Зарегистрироваться
Инсайты автоматически генерируются с помощью искусственного интеллекта на основе текста статьи.
← Назад в лентуЧитать оригинал →
✈️ Подписывайтесь на мой Telegram-канал — там еще больше интересного про AdTech, MarTech, AI и многое другое!