> В чем различия между HTTP/1.1 и HTTP/2 (Go)

Уровень: senior · Роль: backend · Категория: Технические вопросы

Компании: Wildberries, VK, Русклимат, Avito

Стек: Go

> Пример ответа

Короткий ответ

HTTP/2 отличается от HTTP/1.1 мультиплексированием, бинарным протоколом, сжатием заголовков (HPACK), приоритизацией потоков и server push. В HTTP/1.1 одно TCP-соединение обрабатывает один запрос за раз, что приводит к head-of-line blocking и необходимости множества параллельных соединений. HTTP/2 решает это через единое соединение с множеством потоков, снижая задержки и накладные расходы. Для backend-разработчика на Go важно учитывать, что стандартная библиотека net/http автоматически поддерживает HTTP/2 при использовании TLS.

Подробное объяснение

HTTP/1.1 - текстовый протокол, где каждый запрос и ответ - отдельное сообщение в формате строк с заголовками и телом. Ограничения: одно соединение = один запрос в момент времени (pipelining не работает из-за head-of-line blocking), заголовки передаются без сжатия, размер заголовков не ограничен, что ведет к избыточности.

HTTP/2 - бинарный протокол, разбивающий данные на фреймы. Ключевые особенности:

  • Мультиплексирование: множество потоков (streams) в одном TCP-соединении, каждый поток - независимая последовательность фреймов. Это устраняет head-of-line blocking на уровне приложения.
  • Сжатие заголовков: HPACK - статические и динамические таблицы, сокращающие повторяющиеся заголовки.
  • Приоритизация: клиент может указать вес и зависимость потоков, сервер распределяет ресурсы.
  • Server push: сервер может отправлять ресурсы до запроса клиента (например, CSS/JS вместе с HTML).
  • Бинарные фреймы: все данные - фреймы (HEADERS, DATA, SETTINGS, PUSH_PROMISE и др.), что упрощает парсинг и уменьшает ошибки.

Критическое отличие: HTTP/2 не меняет семантику HTTP (методы, статусы, заголовки), но меняет транспорт. HTTP/2 требует TLS в браузерах (h2), хотя протокол позволяет и без шифрования (h2c).

Для Go: net/http автоматически включает HTTP/2 при использовании ListenAndServeTLS. Для h2c нужно использовать golang.org/x/net/http2/h2c. Важно: HTTP/2 не поддерживает некоторые старые механизмы, например, Connection header - он запрещен, а keep-alive управляется на уровне потоков.

На практике

При разработке backend на Go:

  • Производительность: HTTP/2 снижает количество TCP-соединений, что уменьшает нагрузку на файловые дескрипторы и память. Для микросервисов это критично.
  • Graceful shutdown: при HTTP/2 нужно корректно закрывать соединения, ожидая завершения активных потоков. В Go используйте http.Server.Shutdown с контекстом.
  • Прокси и балансировщики: если за Go-сервисом стоит nginx или envoy, они должны поддерживать HTTP/2 upstream, иначе будет конвертация в HTTP/1.1.
  • Server push: в Go доступен через http.Pusher интерфейс, но на практике его редко используют - он может ухудшить производительность при неправильном применении.
  • Таймауты: при HTTP/2 мультиплексирование может маскировать медленные запросы - один поток не блокирует другие, но нужно настраивать таймауты на уровне потоков (например, через http.Server.ReadTimeout и WriteTimeout).
  • Отладка: curl с флагом --http2 для проверки, инструменты типа httpstat или gRPC (который работает поверх HTTP/2).

Пример кода

GO
package main
import (
"fmt"
"net/http"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
// Проверяем, что клиент использует HTTP/2
if r.ProtoMajor == 2 {
fmt.Fprintf(w, "HTTP/2 request\n")
} else {
fmt.Fprintf(w, "HTTP/1.1 request\n")
}
})
// HTTP/2 автоматически включается при использовании TLS
server := &http.Server{
Addr: ":8443",
Handler: mux,
}
// Для h2c (без TLS) - используйте golang.org/x/net/http2/h2c
// h2s := &http2.Server{}
// handler := h2c.NewHandler(mux, h2s)
// server := &http.Server{Addr: ":8080", Handler: handler}
err := server.ListenAndServeTLS("cert.pem", "key.pem")
if err != nil {
panic(err)
}
}

Как отвечать на собеседовании

Начните с ключевого отличия - мультиплексирование и устранение head-of-line blocking. Затем перечислите остальные фичи: бинарный формат, HPACK, приоритизация, server push. Подчеркните, что семантика HTTP не изменилась - это транспортное улучшение.

Для senior-позиции важно показать понимание trade-off: HTTP/2 сложнее в отладке, требует TLS, не решает head-of-line blocking на уровне TCP (это решает HTTP/3 с QUIC). Упомяните, что в Go net/http автоматически поддерживает HTTP/2, но для h2c нужен отдельный пакет.

Приведите пример из практики: как HTTP/2 влияет на проектирование API (меньше соединений, но нужно аккуратнее с таймаутами). Если спросят про производительность - скажите, что прирост в основном на клиентской стороне и для множества мелких запросов.

Что проверяет интервьюер

  • Понимание протокольных различий, а не просто заученных фич.
  • Умение объяснить, почему HTTP/2 решает проблемы HTTP/1.1 (head-of-line blocking, избыточность заголовков).
  • Знание ограничений HTTP/2 (TCP-level HOL, сложность отладки, необходимость TLS).
  • Практический опыт: как это влияет на backend-разработку, настройку серверов, прокси.
  • Для Go - знание стандартной библиотеки и особенностей (автоматическое включение HTTP/2, h2c, http.Pusher).

Типичные ошибки

  • Утверждение, что HTTP/2 заменяет HTTP/1.1 полностью - на самом деле это эволюция, и HTTP/1.1 все еще используется.
  • Игнорирование того, что HTTP/2 не решает head-of-line blocking на уровне TCP - это делает только HTTP/3.
  • Путаница между server push и WebSocket - это разные механизмы.
  • Забывают, что HTTP/2 требует TLS в браузерах, и не упоминают h2c для внутренних сервисов.
  • В Go - попытка использовать HTTP/2 без TLS через стандартный ListenAndServe (не работает), или непонимание, что net/http автоматически включает HTTP/2 при наличии TLS.
  • Неправильное утверждение, что HTTP/2 ускоряет одиночные большие запросы - он оптимизирует множество параллельных мелких.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью