Почему HTTP-запросы на сервере виснут?

Вопрос: почему HTTP-запросы «виснут» и блокируют воркеры?

Линия поддержки
Линия поддержки Ответы на вопросы пользователей
8 декабря 2025

Изображение записи

Комментарий пользователя

Здравствуйте! Делаю запросы к внешним API через requests. Иногда процесс зависает на одном запросе и воркеры перестают обслуживать клиентов. Подскажите, что я упускаю и как это исправить?

Максим Белов Пользователь

Ответ специалиста

Добрый день, Максим! Это классическая ситуация — обычно виноваты два простых момента: нет таймаутов на запросах и нет адекватной стратегии повторов при временных ошибках. 

По умолчанию requests.get() может ждать ответ бесконечно, и один «залипший» вызов способен заглушить поток или воркер. Что можно сделать: использовать Session (чтобы рециклировать соединения), настроить Retry с backoff и всегда передавать timeout в виде (connect, read).

  • Антон Земцов

    Антон Земцов

    Младший бэкенд-разработчик Python

Вот шаблон, который можно доработать и вставить в проект:


      import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
def make_session(retries=3, backoff=0.5, pool_maxsize=10):
    s = requests.Session()
    retry = Retry(
        total=retries,
        backoff_factor=backoff,
        status_forcelist=(429, 500, 502, 503, 504),
        allowed_methods=frozenset(["HEAD","GET","OPTIONS","POST","PUT","DELETE"]),
        respect_retry_after_header=True
    )
    adapter = HTTPAdapter(max_retries=retry, pool_maxsize=pool_maxsize)
    s.mount("https://", adapter)
    s.mount("http://", adapter)
    return s

А в месте вызова всегда указывайте таймаут и ловите исключения, чтобы процесс не висел:


      sess = make_session()
try:
    r = sess.get("https://api.example.com/data", timeout=(3.0, 10.0))
    r.raise_for_status()
    payload = r.json()
except requests.exceptions.Timeout:
    print("request timed out")
except requests.exceptions.HTTPError as e:
    print("http error", e)
except requests.exceptions.RequestException as e:
    print("network error", e)

Есть еще практические моменты, которые часто помогают

  • Не включайте ретраи для небезопасных операций без идемпотентности (некоторые POST могут повторяться).
  • Логируйте метрики по таймаутам и retry, чтобы быстро увидеть проблемные внешние сервисы.
  • Ограничьте параллельность вызовов к одному внешнему API (семафор или очередь), чтобы не создавать thundering herd.

На уровне процесса не полагайтесь только на код — задайте worker timeout в Gunicorn/uWSGI, чтобы один долгий запрос не съедал все воркеры. Для асинхронного стека те же принципы: httpx/aiohttp, таймауты, семафоры и retry-обертки.

Мы продолжим публиковать актуальные инструкции по работе с инфраструктурой. Следите за обновлениями Академии Selectel, чтобы быть в курсе лучших практик.