http.Client использует http.Transport для управления пулом TCP-соединений. По умолчанию используется http.DefaultTransport:
// Дефолтные значения DefaultTransport:
&http.Transport{
MaxIdleConns: 100, // всего idle-соединений
MaxIdleConnsPerHost: 2, // idle-соединений на хост
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
}
MaxIdleConnsPerHost=2 - узкое место при высокой нагрузке на один хост: лишние соединения закрываются и создаются заново (TCP handshake + TLS). При нагрузке стоит увеличить:
client := &http.Client{
Transport: &http.Transport{
MaxIdleConnsPerHost: 100, // для высоконагруженных сервисов
},
}
Соединение возвращается в пул только если resp.Body полностью прочитан и закрыт.