Ответ вслух Senior net/http и middleware обновлено

Надёжный HTTP-клиент в Go

Вопрос

Сервис часто ходит во внешние API. Как вы настроите HTTP-клиент, чтобы он был быстрым и надёжным?

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Создаю один клиент на сервис и переиспользую: Transport внутри держит пул соединений, и новый Transport на каждый запрос означает новые TCP и TLS handshake и утечку пулов.

Что должно прозвучать в ответе

  • Один долгоживущий http.Client с общим Transport на сервис

  • Таймауты: Client.Timeout или ctx с дедлайном, плюс таймауты соединения, TLS и ResponseHeaderTimeout

  • Пул соединений: MaxIdleConns, MaxIdleConnsPerHost под параллелизм, IdleConnTimeout

  • Всегда закрывать Body и дочитывать его для переиспользования соединения

  • Ретраи только идемпотентных запросов с backoff и джиттером, circuit breaker

  • Проверка StatusCode, ограничение размера ответа, метрики и трейсинг

Что могут спросить следом

  • Почему нельзя создавать новый Transport на каждый запрос?
  • Как понять, что соединения не переиспользуются?

Разбор

Создаю один клиент на сервис и переиспользую: Transport внутри держит пул соединений, и новый Transport на каждый запрос означает новые TCP и TLS handshake и утечку пулов. Таймауты на всех уровнях: DialContext с таймаутом соединения, TLSHandshakeTimeout, ResponseHeaderTimeout, а общее время запроса через контекст с дедлайном от вызывающего. Пул: MaxIdleConnsPerHost поднимаю до ожидаемого параллелизма к одному хосту, по умолчанию там 2, и это частая причина TIME_WAIT и задержек. После ответа всегда defer resp.Body.Close(), а тело дочитываю или ограничиваю io.LimitReader. Сеть даёт ошибку в err, а 500 нет, поэтому проверяю StatusCode. Ретраи только для идемпотентных методов и ответов 502, 503, 504, с экспоненциальным backoff и джиттером, с бюджетом ретраев, плюс circuit breaker, чтобы не добивать лежащий сервис. Метрики по хосту и коду, трейсинг через otelhttp. Переиспользование соединений проверяю через httptrace (поле Reused) или по метрикам числа соединений.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.

Термины по теме