Таймауты и повторные запросы при работе через прокси: как настроить

Таймауты и повторные запросы при работе через прокси: как настроить

При работе через прокси задавайте два таймаута — на подключение (5–10 секунд) и на ответ (20–30 секунд), а повторяйте только временные ошибки: таймауты, обрывы соединения, ответы 429 и 502–504. Между попытками пауза должна расти, а общее число попыток — ограничиваться 3–5.

Коротко

  • Без таймаута запрос может висеть бесконечно: в requests по умолчанию его нет.
  • Повторять стоит только временные сбои; ошибки 400, 404 и 407 повтор не исправит.
  • Пауза между попытками растёт по экспоненте со случайной добавкой, а на 429 — берётся из заголовка Retry-After.
  • Если ошибок стало много сразу, лучше остановить сбор на паузу, чем умножать повторы.

Почему через прокси таймауты нужны особенно

Прямой запрос проходит путь «ваш сервер → сайт». Через прокси путь длиннее: ваш сервер → прокси → иногда устройство пользователя в другом городе → сайт. На каждом участке может быть задержка или обрыв, и без таймаута скрипт будет ждать ответа, который не придёт.

У резидентных и мобильных прокси время ответа к тому же сильнее колеблется: адрес принадлежит реальному устройству с домашним или сотовым каналом. Почему скорость скачет, разобрали в статье «Почему скорость через прокси скачет».

Какие бывают таймауты

Три таймаута

Таймаут подключения (connect timeout) — сколько ждать, пока установится соединение с прокси и через него с сайтом.

Таймаут чтения (read timeout) — сколько ждать очередной порции данных от сервера после подключения.

Общий таймаут (total timeout) — верхняя граница на весь запрос целиком, от подключения до последнего байта.

Таймаут чтения — это не время на всю загрузку. Если сервер отдаёт данные медленно, но без долгих пауз, запрос может длиться дольше таймаута чтения. Чтобы ограничить запрос целиком, нужен общий таймаут. В aiohttp он встроен, а в requests и httpx его придётся задать своей обёрткой.

Какие значения ставить

Тип проксиПодключениеЧтение
Серверные и ISP5 с15–20 с
Резидентные10 с20–30 с
Мобильные10–15 с30 с
Стартовые значения таймаутов, которые стоит подстроить по своим замерам

Точнее значения подбираются по логам: посмотрите, за сколько отвечают 95% успешных запросов, и поставьте таймаут чтения в полтора-два раза больше. Слишком короткий таймаут превращает медленные, но рабочие ответы в ошибки и лишние повторы.

Какие ошибки повторять, а какие нет

ОшибкаПовторять?Что делать
Таймаут, обрыв соединенияДаПовторить с паузой, при ротации — уже с другого адреса
429 Too Many RequestsДа, после паузыВыдержать паузу из Retry-After и снизить частоту
502, 503, 504ДаВременная проблема на стороне сайта или прокси
403, CAPTCHAОсторожноНе повторять сразу: сначала снизить частоту и проверить заголовки
407 Proxy Authentication RequiredНетИсправить логин, пароль или белый список IP
400, 404, 410НетОшибка в самом запросе или страницы нет
Какие ответы и ошибки имеет смысл повторять

Если прокси не подключается совсем, повторы не помогут — пройдите по чек-листу из статьи «Почему прокси не подключается». Про ответы 403 и CAPTCHA — в материале «Почему сайт ограничивает доступ».

Важно. Автоматически повторяйте только запросы, которые безопасно выполнить дважды: GET, HEAD, OPTIONS. Повтор POST-запроса может, например, отправить форму второй раз.

Как выбирать паузу между попытками

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

Пауза = min(предел, база × 2 в степени номера попытки) + случайная добавка

При базе 1 секунда паузы будут примерно 1, 2, 4, 8 секунд. Случайная добавка нужна, чтобы сотни потоков, получивших ошибку одновременно, не повторили запросы в одну и ту же секунду. Предел не даёт паузе вырасти до минут.

Если сервер прислал заголовок Retry-After, он важнее формулы: ждите столько, сколько указано.

Настройка в requests

В requests повторы настраиваются через класс Retry из библиотеки urllib3, на которой requests построен. Он сам выдерживает растущую паузу и учитывает Retry-After.

Python

import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

retry = Retry(
    total=4,
    connect=3,
    read=3,
    backoff_factor=1,
    status_forcelist=[429, 502, 503, 504],
    allowed_methods=["GET", "HEAD", "OPTIONS"],
    respect_retry_after_header=True,
)

session = requests.Session()
session.mount("http://", HTTPAdapter(max_retries=retry))
session.mount("https://", HTTPAdapter(max_retries=retry))
session.proxies.update({
    "http": "http://login:password@host:port",
    "https": "http://login:password@host:port",
})

r = session.get("https://example.com/", timeout=(10, 30))

Кортеж timeout=(10, 30) задаёт таймаут подключения 10 секунд и чтения 30 секунд. В urllib3 версии 2 и новее можно добавить параметр backoff_jitter — он добавляет к паузе случайную часть.

Настройка в aiohttp

В aiohttp встроенных повторов нет, поэтому их удобно написать небольшой функцией.

Python

import asyncio
import random
import aiohttp

RETRY_STATUSES = {429, 502, 503, 504}

async def fetch(session, url, proxy, attempts=4, base=1.0, cap=30.0):
    for attempt in range(attempts):
        try:
            async with session.get(url, proxy=proxy) as r:
                if r.status not in RETRY_STATUSES:
                    return r.status, await r.text()
                retry_after = r.headers.get("Retry-After")
        except (aiohttp.ClientConnectionError, asyncio.TimeoutError):
            retry_after = None
        if attempt == attempts - 1:
            break
        if retry_after and retry_after.isdigit():
            delay = int(retry_after)
        else:
            delay = min(cap, base * 2 ** attempt) + random.uniform(0, base)
        await asyncio.sleep(delay)
    return None, None

timeout = aiohttp.ClientTimeout(total=40, sock_connect=10, sock_read=30)

Сессию создавайте с этим таймаутом: aiohttp.ClientSession(timeout=timeout). Параметр total ограничивает весь запрос, sock_connect и sock_read — подключение и ожидание данных.

Когда остановить сбор, а не повторять

Повторы помогают при единичных сбоях. Если ошибок стало много одновременно — сайт недоступен, сменил защиту или вы превысили допустимую частоту, — повторы только умножат нагрузку и расход трафика.

  • Следите за долей ошибок в окне
    Например, за последние 200 запросов. Если больше 20–30% закончились ошибкой, это уже не случайность.
  • Ставьте сбор на паузу
    Остановите новые запросы на несколько минут, затем отправьте один пробный. Такой приём называют «предохранителем» (circuit breaker).
  • Снижайте частоту после паузы
    Возвращайтесь к прежней скорости постепенно, а не сразу всеми потоками.
  • Пишите в лог причину каждой ошибки
    Без разбивки по кодам невозможно понять, что случилось: перегрузка сайта, проблема с прокси или ошибка в коде.

Как это устроено у нас

В резидентных прокси Proxy.Market при ротации на каждый запрос новое соединение, как правило, получает другой адрес из пула. Поэтому повтор после таймаута обычно уходит уже через другое устройство, и случайный сбой одного узла не тормозит весь сбор.

Если нужна предсказуемая скорость ответа и короткие таймауты, посмотрите на ISP-прокси и серверные прокси IPv4: они работают через каналы дата-центров, и задержка у них стабильнее. Как выбрать тип прокси по задержке и скорости, разобрали в статье «Задержка и пропускная способность».


Частые вопросы

Какой таймаут ставить для резидентных прокси?
Для начала — 10 секунд на подключение и 20–30 секунд на чтение. Потом подстройте по логам: таймаут чтения в полтора-два раза больше времени, за которое отвечают 95% успешных запросов.

Сколько раз повторять запрос?
Обычно достаточно 3–5 попыток. Если запрос не прошёл за это время, проблема, скорее всего, не случайная, и дальнейшие повторы только тратят трафик.

Нужно ли повторять ошибку 407?
Нет. Ошибка 407 означает, что прокси не принял данные для входа. Проверьте логин, пароль и белый список IP в личном кабинете.

Тратят ли повторы трафик?
Да. При оплате за гигабайт каждый повтор оплачивается как обычный запрос, поэтому ограничение числа попыток напрямую экономит бюджет.

Много таймаутов через прокси?

Пришлите в поддержку тип прокси, целевой сайт и долю ошибок — подскажем, в чём может быть причина.

Задать вопрос