Ответ
Правильная настройка таймаутов критически важна для создания надежных и предсказуемых HTTP-клиентов. В Go существует несколько уровней таймаутов, которые настраиваются в http.Client
и http.Transport
.
Основные виды таймаутов:
http.Client.Timeout
: Общий таймаут. Ограничивает общее время выполнения всего запроса, включая установку соединения, отправку запроса, чтение заголовков и тела ответа. Это самый простой и грубый способ установить ограничение.net.Dialer.Timeout
: Таймаут на установку соединения. Ограничивает время, затрачиваемое на установку TCP-соединения с сервером. Настраивается внутриhttp.Transport
.http.Transport.ResponseHeaderTimeout
: Таймаут на чтение заголовков. Ограничивает время ожидания заголовков ответа после полной отправки запроса.http.Transport.TLSHandshakeTimeout
: Таймаут на TLS-рукопожатие. Ограничивает время, затрачиваемое на установку безопасного TLS-соединения.http.Transport.IdleConnTimeout
: Таймаут простоя соединения. Определяет, как долго неиспользуемое соединение будет оставаться открытым в пуле. Важно для управления ресурсами.
Пример детальной настройки:
client := &http.Client{
// Общий таймаут на весь запрос
Timeout: 30 * time.Second,
Transport: &http.Transport{
DialContext: (&net.Dialer{
// Таймаут на установку TCP-соединения
Timeout: 5 * time.Second,
}).DialContext,
// Таймаут на TLS-рукопожатие
TLSHandshakeTimeout: 10 * time.Second,
// Таймаут на получение заголовков ответа
ResponseHeaderTimeout: 15 * time.Second,
// Таймаут на 100-Continue от сервера
ExpectContinueTimeout: 1 * time.Second,
},
}
Рекомендации:
- Всегда устанавливайте таймауты. Нулевое значение означает отсутствие таймаута, что может привести к вечной блокировке горутины.
- Для внутренних сервисов (внутри одного дата-центра): обычно достаточно коротких таймаутов (1-5 секунд).
- Для внешних API: таймауты должны быть больше (5-30 секунд), но всегда меньше, чем таймаут на стороне вашего клиента (например, таймаут HTTP-запроса от пользователя).
- Баланс:
Client.Timeout
должен быть больше суммы остальных таймаутов, чтобы дать им сработать. Например:DialTimeout
(5s) +ResponseHeaderTimeout
(10s) <Client.Timeout
(30s).