Пул соединений и прокси
Конфигурация пула соединений
Пул соединений — ключевой фактор производительности HTTP-клиента. HTTPC управляет пулом через ConnectionConfig.
cfg := httpc.DefaultConfig()
// Параметры пула соединений
cfg.Connection.MaxIdleConns = 100 // Глобальное максимальное число простаивающих соединений
cfg.Connection.MaxConnsPerHost = 20 // Максимальное число соединений на хост
cfg.Timeouts.IdleConn = 120 * time.Second // Время удержания простаивающих соединенийОписание параметров
| Параметр | По умолчанию | Описание |
|---|---|---|
MaxIdleConns | 50 | Глобальное максимальное число простаивающих соединений |
MaxConnsPerHost | 10 | Максимальное число соединений на хост (активных + простаивающих) |
IdleConn | 90s | Таймаут простаивающего соединения, после истечения закрывается |
Dial | 10s | Таймаут установки соединения |
TLSHandshake | 10s | Таймаут TLS-рукопожатия |
ResponseHeader | 0 | Отключено (используется таймаут Request) |
Рекомендации по сценариям
| Сценарий | MaxIdleConns | MaxConnsPerHost | IdleConn |
|---|---|---|---|
| Высоконагруженные API | 100 | 20 | 120s |
| Обычные сервисы | 50 | 10 | 90s |
| Редкие запросы | 10 | 2 | 30s |
| Внутренние микросервисы | 50 | 10 | 60s |
TIP
MaxConnsPerHost включает активные и простаивающие соединения. Новые запросы сверх этого лимита будут ожидать освобождения соединения.
Прокси
HTTPC поддерживает четыре режима прокси, выбираемых автоматически по приоритету. Все настройки прокси задаются в ConnectionConfig.
Ручной прокси
Укажите фиксированный прокси через ProxyURL (высший приоритет):
cfg := httpc.DefaultConfig()
cfg.Connection.ProxyURL = "http://proxy.example.com:8080"
client, _ := httpc.New(cfg)Прокси с аутентификацией:
cfg.Connection.ProxyURL = "http://user:[email protected]:8080"TIP
Метод Config.String() автоматически маскирует имя пользователя и пароль в URL прокси.
SOCKS5-прокси
cfg := httpc.DefaultConfig()
cfg.Connection.ProxyURL = "socks5://proxy.example.com:1080"Автообнаружение системного прокси
Включите для автоматического определения настроек прокси ОС:
cfg := httpc.DefaultConfig()
cfg.Connection.EnableSystemProxy = true| Платформа | Источник |
|---|---|
| Windows | Реестр Internet Settings |
| macOS | Системные настройки сетевого прокси |
| Linux | Переменные окружения HTTP_PROXY / HTTPS_PROXY |
Пул прокси
Когда нужно распределить запросы между несколькими IP-прокси (скрапинг, распределение нагрузки, ротация IP), пул прокси обеспечивает автоматическую ротацию, пассивный размыкатель цепи и переключение по статус-коду — без внешних компонентов.
Базовое использование
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 | []string | nil | Список URL прокси |
ProxyPoolStrategy | ProxyStrategy | RoundRobin | Стратегия выбора |
ProxyFailureThreshold | int | 3 (0 → по умолч.) | Порог последовательных сбоев для размыкания |
ProxyCooldown | time.Duration | 30s (0 → по умолч.) | Время ожидания для разомкнутого прокси |
ProxyRotateOnStatus | []int | nil | Статус-коды, запускающие ротацию прокси |
Стратегия выбора
| Стратегия | Константа | Описание |
|---|---|---|
| Round-robin | ProxyStrategyRoundRobin | Циклический перебор по порядку; повторы автоматически переходят к следующему прокси |
| Случайный | ProxyStrategyRandom | Равномерный случайный выбор из здоровых прокси |
Round-robin (по умолчанию) автоматически выбирает другой IP-прокси при повторе — каждый повтор сдвигает курсор, естественным образом переходя к следующему прокси.
Пассивный размыкатель цепи
Пул прокси имеет встроенную пассивную проверку работоспособности. Только сбои на уровне соединения (dial/TLS) запускают размыкание; HTTP статус-коды — нет:
Сбой соединения с прокси
↓
Счётчик сбоев +1
↓
Последовательных сбоев ≥ ProxyFailureThreshold → Размыкание (исключение из ротации)
↓
Ожидание ProxyCooldown → Полуоткрытый пробник (возврат в ротацию)
↓
Успех → Сброс счётчика, замыкание
Первый сбой → Повторное размыканиеcfg.Connection.ProxyFailureThreshold = 5 // Терпимее к временным сбоям
cfg.Connection.ProxyCooldown = 60 * time.Second // Более длительное ожиданиеКогда все прокси разомкнуты, возвращается прокси с кратчайшим временем ожидания (ближе всего к восстановлению) как резерв, вместо немедленного отказа.
Ротация по статус-коду
Для сценариев блокировки IP по Cloudflare/WAF — автоматический повтор с другим прокси при возврате определённых статус-кодов:
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 | Всегда использовать указанный прокси (однопрокси-режим) |
| 2 | ProxyPool | Ротация по пулу прокси |
| 3 | EnableSystemProxy | Автообнаружение системного прокси |
| 4 (низший) | Нет | Прямое подключение |
TIP
Если заданы и ProxyURL, и ProxyPool, применяется ProxyURL. Для использования пула прокси очистите ProxyURL.
Встроенная безопасность
Функции, связанные с прокси, автоматически обрабатывают следующие аспекты безопасности — ручная настройка не требуется:
- Освобождение от SSRF: Адреса хостов прокси автоматически добавляются в список освобождений SSRF, никогда не блокируются проверками частных IP
- Дедупликация: Записи с одинаковыми
host:portавтоматически объединяются, предотвращая перекос ротации и двойной подсчёт - Проверка URL: Все URL прокси проходят проверку безопасности (защита от CRLF-инъекций, белый список протоколов)
Полное описание полей см. в Конфигурация API — Пул прокси.
DNS-over-HTTPS
Включение DoH снижает задержку разрешения DNS и предотвращает перехват DNS:
cfg := httpc.DefaultConfig()
cfg.Connection.EnableDoH = true
cfg.Connection.DoHCacheTTL = 5 * time.MinuteПровайдеры DoH по умолчанию (по приоритету):
| Провайдер | Адрес | Описание |
|---|---|---|
| Cloudflare | 1.1.1.1/dns-query | Самый быстрый, приоритет конфиденциальности |
dns.google/resolve | Глобальное покрытие | |
| AliDNS | dns.alidns.com/resolve | Оптимизация для Китая |
TIP
При включении DoH результаты разрешения DNS кэшируются на время DoHCacheTTL. Если все провайдеры DoH недоступны, выполняется откат к системному DNS.
HTTP/2
HTTP/2 включён по умолчанию (требуется TLS):
cfg := httpc.DefaultConfig()
cfg.Connection.EnableHTTP2 = false // Отключить HTTP/2Возможности HTTP/2:
- Мультиплексирование: одно соединение обрабатывает несколько параллельных запросов
- Сжатие заголовков: уменьшение передачи повторяющихся заголовков
- Серверный пуш
Повторное использование пула объектов
Внутри HTTPC переиспользует объекты ответов движка и построители строк через sync.Pool, снижая нагрузку на GC; Result создаётся заново для каждого запроса и утилизируется GC.
result, err := client.Get(url)
if err != nil {
return err
}
// Result создаётся заново для каждого запроса, утилизируется GC, ручное освобождение не требуетсяВ высоконагруженных сценариях переиспользование внутреннего пула объектов значительно снижает нагрузку на GC.
Паттерны параллельных запросов
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 |
Полный анализ антипаттернов производительности и рекомендации по оптимизации см. в Оптимизация производительности.
Что дальше
- Оптимизация производительности - руководство по настройке производительности
- Конфигурация API - справочник по соединениям и прокси
- Обзор безопасности - безопасность SSRF и TLS