Синхронный HTTP-клиент в async-эндпоинте: почему тормозит весь сервис, а не одна ручка
Сервис на FastAPI отправляет заявки в банк. Эндпоинт объявлен как async def, а внутри стоит синхронный вызов:
@app.post("/applications")
async def create_application(payload: ApplicationIn):
response = requests.post(BANK_URL, json=payload.dict(), timeout=5) # отвечает ~800 мс
return await service.save(payload, response.json())
Под нагрузкой около 200 RPS выросло p99 всех ручек сервиса, включая проверку доступности /health, которая ходит только в память.
Почему деградировала не одна ручка, а весь сервис?
- Все запросы воркера обслуживает один event loop, и синхронный вызов держит его целиком
- Библиотека requests медленнее асинхронных клиентов: замена на более быстрый клиент решит проблему
- Причина в GIL: async-код в принципе не может выполняться одновременно с сетевыми вызовами
- Не хватает реплик сервиса — единственное решение здесь горизонтальное масштабирование под пик
