Skip to content

Пул соединений и прокси

Конфигурация пула соединений

Пул соединений — ключевой фактор производительности HTTP-клиента. HTTPC управляет пулом через ConnectionConfig.

go
cfg := httpc.DefaultConfig()

// Параметры пула соединений
cfg.Connection.MaxIdleConns = 100         // Глобальное максимальное число простаивающих соединений
cfg.Connection.MaxConnsPerHost = 20       // Максимальное число соединений на хост
cfg.Timeouts.IdleConn = 120 * time.Second // Время удержания простаивающих соединений

Описание параметров

ПараметрПо умолчаниюОписание
MaxIdleConns50Глобальное максимальное число простаивающих соединений
MaxConnsPerHost10Максимальное число соединений на хост (активных + простаивающих)
IdleConn90sТаймаут простаивающего соединения, после истечения закрывается
Dial10sТаймаут установки соединения
TLSHandshake10sТаймаут TLS-рукопожатия
ResponseHeader0Отключено (используется таймаут Request)

Рекомендации по сценариям

СценарийMaxIdleConnsMaxConnsPerHostIdleConn
Высоконагруженные API10020120s
Обычные сервисы501090s
Редкие запросы10230s
Внутренние микросервисы501060s

TIP

MaxConnsPerHost включает активные и простаивающие соединения. Новые запросы сверх этого лимита будут ожидать освобождения соединения.

Прокси

HTTPC поддерживает четыре режима прокси, выбираемых автоматически по приоритету. Все настройки прокси задаются в ConnectionConfig.

Ручной прокси

Укажите фиксированный прокси через ProxyURL (высший приоритет):

go
cfg := httpc.DefaultConfig()
cfg.Connection.ProxyURL = "http://proxy.example.com:8080"

client, _ := httpc.New(cfg)

Прокси с аутентификацией:

go
cfg.Connection.ProxyURL = "http://user:[email protected]:8080"

TIP

Метод Config.String() автоматически маскирует имя пользователя и пароль в URL прокси.

SOCKS5-прокси

go
cfg := httpc.DefaultConfig()
cfg.Connection.ProxyURL = "socks5://proxy.example.com:1080"

Автообнаружение системного прокси

Включите для автоматического определения настроек прокси ОС:

go
cfg := httpc.DefaultConfig()
cfg.Connection.EnableSystemProxy = true
ПлатформаИсточник
WindowsРеестр Internet Settings
macOSСистемные настройки сетевого прокси
LinuxПеременные окружения HTTP_PROXY / HTTPS_PROXY

Пул прокси

Когда нужно распределить запросы между несколькими IP-прокси (скрапинг, распределение нагрузки, ротация IP), пул прокси обеспечивает автоматическую ротацию, пассивный размыкатель цепи и переключение по статус-коду — без внешних компонентов.

Базовое использование

go
cfg := httpc.DefaultConfig()
cfg.Connection.ProxyPool = []string{
    "http://proxy1:8080",
    "http://proxy2:8080",
    "http://proxy3:8080",
}
cfg.Connection.ProxyPoolStrategy = httpc.ProxyStrategyRoundRobin // по умолчанию

client, err := httpc.New(cfg)

Каждый запрос автоматически выбирает прокси из пула. Поддерживаются протоколы http, https, socks5, socks5h.

ПолеТипПо умолчаниюОписание
ProxyPool[]stringnilСписок URL прокси
ProxyPoolStrategyProxyStrategyRoundRobinСтратегия выбора
ProxyFailureThresholdint3 (0 → по умолч.)Порог последовательных сбоев для размыкания
ProxyCooldowntime.Duration30s (0 → по умолч.)Время ожидания для разомкнутого прокси
ProxyRotateOnStatus[]intnilСтатус-коды, запускающие ротацию прокси

Стратегия выбора

СтратегияКонстантаОписание
Round-robinProxyStrategyRoundRobinЦиклический перебор по порядку; повторы автоматически переходят к следующему прокси
СлучайныйProxyStrategyRandomРавномерный случайный выбор из здоровых прокси

Round-robin (по умолчанию) автоматически выбирает другой IP-прокси при повторе — каждый повтор сдвигает курсор, естественным образом переходя к следующему прокси.

Пассивный размыкатель цепи

Пул прокси имеет встроенную пассивную проверку работоспособности. Только сбои на уровне соединения (dial/TLS) запускают размыкание; HTTP статус-коды — нет:

text
Сбой соединения с прокси

Счётчик сбоев +1

Последовательных сбоев ≥ ProxyFailureThreshold → Размыкание (исключение из ротации)

Ожидание ProxyCooldown → Полуоткрытый пробник (возврат в ротацию)

Успех → Сброс счётчика, замыкание
Первый сбой → Повторное размыкание
go
cfg.Connection.ProxyFailureThreshold = 5           // Терпимее к временным сбоям
cfg.Connection.ProxyCooldown = 60 * time.Second    // Более длительное ожидание

Когда все прокси разомкнуты, возвращается прокси с кратчайшим временем ожидания (ближе всего к восстановлению) как резерв, вместо немедленного отказа.

Ротация по статус-коду

Для сценариев блокировки IP по Cloudflare/WAF — автоматический повтор с другим прокси при возврате определённых статус-кодов:

go
cfg := httpc.DefaultConfig()
cfg.Connection.ProxyPool = []string{
    "http://proxy1:8080",
    "http://proxy2:8080",
    "http://proxy3:8080",
}
cfg.Connection.ProxyRotateOnStatus = []int{403}  // Ротация прокси при 403
cfg.Retry.MaxRetries = 3                          // Повторы должны быть включены

client, err := httpc.New(cfg)

Ротация по статус-коду ≠ Размыкание

Ротация, запущенная ProxyRotateOnStatus, не размыкает прокси — блокировки IP часто зависят от цели (прокси, заблокированный на сайте A, может работать на сайте B). Размыкание запускается только сбоями на уровне соединения. Требуется Retry.MaxRetries > 0.

Когда ProxyRotateOnStatus задан и пул содержит несколько прокси, бюджет повторов автоматически повышается до len(ProxyPool) - 1 (ограничен пределом MaxRetries = 10), гарантируя, что каждый прокси получит шанс.

Приоритет прокси

При одновременной настройке нескольких режимов прокси они применяются по приоритету:

ПриоритетНастройкаПоведение
1 (высший)ProxyURLВсегда использовать указанный прокси (однопрокси-режим)
2ProxyPoolРотация по пулу прокси
3EnableSystemProxyАвтообнаружение системного прокси
4 (низший)НетПрямое подключение

TIP

Если заданы и ProxyURL, и ProxyPool, применяется ProxyURL. Для использования пула прокси очистите ProxyURL.

Встроенная безопасность

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

  • Освобождение от SSRF: Адреса хостов прокси автоматически добавляются в список освобождений SSRF, никогда не блокируются проверками частных IP
  • Дедупликация: Записи с одинаковыми host:port автоматически объединяются, предотвращая перекос ротации и двойной подсчёт
  • Проверка URL: Все URL прокси проходят проверку безопасности (защита от CRLF-инъекций, белый список протоколов)

Полное описание полей см. в Конфигурация API — Пул прокси.

DNS-over-HTTPS

Включение DoH снижает задержку разрешения DNS и предотвращает перехват DNS:

go
cfg := httpc.DefaultConfig()
cfg.Connection.EnableDoH = true
cfg.Connection.DoHCacheTTL = 5 * time.Minute

Провайдеры DoH по умолчанию (по приоритету):

ПровайдерАдресОписание
Cloudflare1.1.1.1/dns-queryСамый быстрый, приоритет конфиденциальности
Googledns.google/resolveГлобальное покрытие
AliDNSdns.alidns.com/resolveОптимизация для Китая

TIP

При включении DoH результаты разрешения DNS кэшируются на время DoHCacheTTL. Если все провайдеры DoH недоступны, выполняется откат к системному DNS.

HTTP/2

HTTP/2 включён по умолчанию (требуется TLS):

go
cfg := httpc.DefaultConfig()
cfg.Connection.EnableHTTP2 = false // Отключить HTTP/2

Возможности HTTP/2:

  • Мультиплексирование: одно соединение обрабатывает несколько параллельных запросов
  • Сжатие заголовков: уменьшение передачи повторяющихся заголовков
  • Серверный пуш

Повторное использование пула объектов

Внутри HTTPC переиспользует объекты ответов движка и построители строк через sync.Pool, снижая нагрузку на GC; Result создаётся заново для каждого запроса и утилизируется GC.

go
result, err := client.Get(url)
if err != nil {
    return err
}
// Result создаётся заново для каждого запроса, утилизируется GC, ручное освобождение не требуется

В высоконагруженных сценариях переиспользование внутреннего пула объектов значительно снижает нагрузку на GC.

Паттерны параллельных запросов

go
func fetchAll(ctx context.Context, urls []string) ([]*httpc.Result, error) {
    results := make([]*httpc.Result, len(urls))
    errs := make([]error, len(urls))

    var wg sync.WaitGroup
    for i, url := range urls {
        wg.Add(1)
        go func(idx int, u string) {
            defer wg.Done()
            result, err := client.Request(ctx, "GET", u)
            results[idx] = result
            errs[idx] = err
        }(i, url)
    }
    wg.Wait()

    for _, err := range errs {
        if err != nil {
            return nil, err
        }
    }
    return results, nil
}

Частые проблемы

ПроблемаПричинаРешение
Много TIME_WAITТаймаут простаивающих соединений слишком короткийУвеличьте таймаут IdleConn
Отказ в соединенииНедостаточно соединений на хостУвеличьте MaxConnsPerHost
Запросы ожидают в очередиПул соединений слишком малУвеличьте MaxIdleConns
Прокси не работаетЗаданы и ProxyURL, и ProxyPoolОчистите ProxyURL, используйте только ProxyPool
Частое размыкание проксиProxyFailureThreshold слишком низкийУвеличьте порог или ProxyCooldown

Полный анализ антипаттернов производительности и рекомендации по оптимизации см. в Оптимизация производительности.

Что дальше