Перейти к содержимому

HTTP/2 как транспорт

HTTP/2 как транспорт gRPC: даёт мультиплексирование (один запрос не блокирует другие), сжатие заголовков (HPACK), бинарный формат (быстрее парсинга) и стриминг (server/client/bidirectional). Решает проблему head-of-line blocking HTTP/1.1.

Введение: Эволюция веб-протокола

Представьте, что вы стоите в очереди в супермаркете. В старой очереди (HTTP/1.1) есть одно капризное правило: пока первый человек не расплатится и не уйдёт, второй не может даже подойти к кассе. Если первый долго выбирает сдачу — очередь стоит. Если нужно передать десять человек — они будут идти строго один за другим.

В новой очереди (HTTP/2) правило другое. Несколько человек могут подходить к кассе одновременно. Пока один расплачивается, второй может задать вопрос, третий — показать бонусную карту. Всё параллельно, всё быстрее.

HTTP/1.1 — это протокол, на котором построен современный веб и большинство REST API. Но у него есть недостатки: каждое соединение обрабатывает один запрос за раз, заголовки не сжимаются, данные передаются в текстовом виде.

HTTP/2 — это следующая версия протокола, которая решает эти проблемы. gRPC выбрал HTTP/2 в качестве транспорта, потому что он даёт мультиплексирование, сжатие заголовков, бинарный формат и стриминг — всё то, что нужно для высокопроизводительных API.

HTTP/2 (Hypertext Transfer Protocol version 2) — это мажорное обновление протокола HTTP, выпущенное в 2015 году. Он сохраняет семантику HTTP (методы, статусы, заголовки, URL), но полностью меняет то, как данные передаются по сети.

HTTP/1.1 vs HTTP/2: Ключевые отличия

ХарактеристикаHTTP/1.1HTTP/2
ФорматТекстовый (человеко-читаемый)Бинарный
СоединенияОдин запрос → одно соединениеОдно соединение → много потоков
ЗаголовкиТекстовые, без сжатияСжатые (HPACK)
БлокировкаHead-of-line blocking (HOL)Нет (мультиплексирование)
Server PushНет (только через SSE/WebSockets)Да (экспериментально)
Приоритеты запросовНетДа
ШифрованиеОпционально (HTTPS)Рекомендовано (HTTP/2 + TLS)

Проблемы HTTP/1.1, которые решил HTTP/2

Проблема 1: Head-of-line blocking (HOL)

В HTTP/1.1 каждое соединение обрабатывает один запрос за раз. Запросы выстраиваются в очередь.

    sequenceDiagram
    participant Client
    participant Server
    
    Client->>Server: Запрос 1 (медленный)
    Note over Server: Обработка 1... (1 сек)
    Server-->>Client: Ответ 1
    
    Client->>Server: Запрос 2
    Note over Server: Обработка 2 (0.1 сек)
    Server-->>Client: Ответ 2
  

Проблема: Быстрый запрос 2 ждёт, пока завершится медленный запрос 1.

Решение HTTP/2: Мультиплексирование — несколько потоков в одном соединении.

    sequenceDiagram
    participant Client
    participant Server
    
    Client->>Server: Запрос 1 (поток 1)
    Client->>Server: Запрос 2 (поток 2)
    
    Note over Server: Обработка 1 (1 сек)
    Note over Server: Обработка 2 (0.1 сек)
    
    Server-->>Client: Ответ 2 (поток 2)
    Server-->>Client: Ответ 1 (поток 1)
  

Результат: Запрос 2 получает ответ, не дожидаясь запроса 1.

Проблема 2: Множество соединений

Чтобы обойти HOL, браузеры открывают 6-8 параллельных соединений к одному домену.

Домен api.example.com
├── Соединение 1: запрос A
├── Соединение 2: запрос B
├── Соединение 3: запрос C
├── Соединение 4: запрос D
├── Соединение 5: запрос E
└── Соединение 6: запрос F

Проблема: Каждое соединение требует ресурсов (память, TCP handshake, TLS handshake).

Решение HTTP/2: Одно соединение, много потоков.

Проблема 3: Несжатые заголовки

Каждый HTTP/1.1 запрос содержит заголовки, которые могут быть большими (иногда до нескольких килобайт). И они повторяются в каждом запросе.

GET /users/123 HTTP/1.1
Host: api.example.com
User-Agent: Mozilla/5.0
Accept: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
Cookie: session_id=abc123

Проблема: Много повторяющихся данных в каждом запросе.

Решение HTTP/2: Сжатие заголовков HPACK (словарь повторяющихся значений).

Проблема 4: Текстовый формат

HTTP/1.1 передаёт данные в текстовом виде (ASCII).

GET /users/123 HTTP/1.1
Host: api.example.com

Проблема: Текст избыточен. “GET” можно было бы закодировать одним байтом, а не тремя.

Решение HTTP/2: Бинарный формат. Парсить байты быстрее, чем текст.

Ключевые особенности HTTP/2

1. Бинарный протокол

HTTP/1.1 передаёт текст. HTTP/2 передаёт бинарные кадры (frames).

Структура кадра:

Длина (3 байта)Тип (1 байт)Флаги (1 байт)Идентификатор потока (4 байта)Данные

Типы кадров:

ТипНазначение
DATAПередача данных (тело ответа)
HEADERSПередача заголовков
PRIORITYУстановка приоритета потока
RST_STREAMСброс потока (ошибка или отмена)
SETTINGSНастройки соединения
PUSH_PROMISEServer Push (объявление будущего ресурса)
PINGПроверка соединения
GOAWAYЗавершение соединения

2. Мультиплексирование (Multiplexing)

Одно TCP соединение может передавать несколько независимых потоков одновременно.

    graph TD
    subgraph "Одно TCP соединение"
        S1[Поток 1: запрос A]
        S2[Поток 2: запрос B]
        S3[Поток 3: запрос C]
        S4[Поток 4: запрос D]
    end
  

Что это даёт:

  • Нет head-of-line blocking
  • Нужно меньше соединений (экономия ресурсов)
  • Лучшее использование пропускной способности

3. Сжатие заголовков (HPACK)

Заголовки сжимаются с использованием статического и динамического словарей.

Статический словарь (61 общий заголовок):

ИндексЗаголовокЗначение
2:methodGET
3:methodPOST
4:path/
5:path/index.html
6:schemehttp
7:schemehttps
8:status200
9:status204

Динамический словарь: Запоминает заголовки, которые встречались в этом соединении.

Пример сжатия:

# Оригинальные заголовки (200 байт)
:method: GET
:path: /users/123
:scheme: https
user-agent: Mozilla/5.0
authorization: Bearer abc123
accept: application/json

# После сжатия HPACK (50 байт)
# :method и :path — ссылки на статический словарь
# authorization — сохранён в динамическом словаре

4. Server Push (экспериментально)

Сервер может отправить ресурсы, не дожидаясь запроса клиента.

    sequenceDiagram
    participant Client
    participant Server
    
    Client->>Server: GET /index.html
    Server-->>Client: PUSH_PROMISE (style.css)
    Server-->>Client: PUSH_PROMISE (script.js)
    Server-->>Client: index.html
    Server-->>Client: style.css
    Server-->>Client: script.js
  

Когда полезно: HTML страница, которая ссылается на CSS, JS, изображения. Сервер отправляет их вместе с HTML.

В gRPC: Server Push используется редко, но теоретически возможен.

5. Приоритеты потоков

Клиент может указать важность каждого потока.

    graph TD
    A[Корень] --> B[Поток 1: 40%]
    A --> C[Поток 2: 30%]
    A --> D[Поток 3: 20%]
    A --> E[Поток 4: 10%]
  

Пример: В браузере запрос HTML имеет высший приоритет, CSS и JS — средний, изображения — низкий.

Как gRPC использует HTTP/2

Заголовки gRPC

Каждый gRPC вызов использует специальные HTTP/2 заголовки.

:method: POST
:path: /example.UserService/GetUser
:scheme: https
content-type: application/grpc
grpc-timeout: 10S
grpc-encoding: gzip
authorization: Bearer token123
ЗаголовокЗначение
:methodВсегда POST (даже для запросов чтения)
:path/{package}.{service}/{method}
content-typeapplication/grpc (или application/grpc+proto)
grpc-timeoutТаймаут вызова (10S — 10 секунд)
grpc-encodingКодирование (сжатие) тела

gRPC кадры поверх HTTP/2

gRPC оборачивает protobuf сообщения в HTTP/2 DATA кадры.

HTTP/2 DATA frame
├── Флаг END_STREAM (последнее сообщение)
└── Данные (сжатый protobuf + 5-байтовый префикс)

Префикс gRPC (5 байт):

БайтНазначение
1Флаг сжатия (0 = нет, 1 = есть)
2-5Длина сообщения (big-endian, 4 байта)

gRPC статус в трейлерах

В отличие от HTTP, где статус в заголовке, gRPC передаёт статус в трейлерах (заголовках после тела).

# После тела ответа
grpc-status: 0
grpc-message: OK
grpc-statusЗначение
0OK
1Canceled
2Unknown
3InvalidArgument
4DeadlineExceeded
5NotFound

HTTP/2 и производительность

Сравнение: HTTP/1.1 + REST vs HTTP/2 + gRPC

Сценарий: Получить 100 пользователей (каждый по одному запросу).

HTTP/1.1 + REST:

  • 100 TCP соединений (или 6 соединений × 17 “пакетов”)
  • 100 TLS handshake (если HTTPS)
  • Head-of-line blocking
  • Заголовки повторяются 100 раз

HTTP/2 + gRPC:

  • 1 TCP соединение
  • 1 TLS handshake
  • Нет HOL
  • Сжатые заголовки (HPACK)

Результат: gRPC может быть в 5-10 раз быстрее для большого количества маленьких запросов.

HTTP/2 и безопасность

HTTP/2 без шифрования (h2c)

HTTP/2 может работать без TLS (h2c — HTTP/2 cleartext), но браузеры его не поддерживают. В gRPC обычно используется HTTP/2 + TLS.

TLS особенности HTTP/2

  • ALPN (Application-Layer Protocol Negotiation): Клиент и сервер договариваются, что будут использовать HTTP/2, а не HTTP/1.1
  • SNI (Server Name Indication): Клиент указывает, к какому домену подключается (важно для виртуального хостинга)

Ограничения HTTP/2

ОграничениеЗначение
Максимум потоков~100 000 (настраивается)
Максимум фреймов в полётеЗависит от window size (настраивается)
Server PushПлохо поддерживается, сложно отлаживать
Head-of-line blocking на TCP уровнеПри потере пакета, все потоки ждут

Важно: HTTP/2 решает HOL на уровне запросов, но не решает HOL на уровне TCP. Если TCP пакет потерян, все потоки ждут его повторной передачи. HTTP/3 (на базе QUIC) решает и эту проблему.

HTTP/2 vs HTTP/3

ХарактеристикаHTTP/2HTTP/3
ТранспортTCPQUIC (UDP-based)
HOL на уровне TCPЕстьНет
ШифрованиеTLS 1.2/1.3TLS 1.3 (всегда)
Поддержка gRPCДа (стабильно)Экспериментально

gRPC уже экспериментирует с HTTP/3 (gRPC-QUIC), но пока стандарт — HTTP/2.

Практические последствия для аналитика

Что нужно знать про HTTP/2 для gRPC

  1. Одно соединение — много потоков. Не нужно пул соединений, как в HTTP/1.1.

  2. Стриминг на уровне протокола. Server streaming, client streaming, bidirectional — нативные возможности HTTP/2.

  3. Сжатие заголовков. Трафик заголовков минимален.

  4. Требуется TLS для продакшена. Без TLS HTTP/2 работает, но не во всех средах.

  5. Не все load balancers поддерживают HTTP/2. Некоторые “понимают” только HTTP/1.1 и разрывают соединение.

Советы по настройке

ПараметрРекомендация
Max concurrent streams1000-10000 (зависит от нагрузки)
Initial window size64KB-1MB (для больших стримов)
KeepaliveВключить (чтобы соединение не закрывалось)
PingПериодические проверки соединения

Резюме для системного аналитика

  1. HTTP/2 — транспорт gRPC. Он даёт мультиплексирование, сжатие заголовков, бинарный формат и стриминг.

  2. Главное преимущество — мультиплексирование. Одно соединение обрабатывает много параллельных запросов. Нет head-of-line blocking на уровне запросов.

  3. Бинарный протокол быстрее парсится и компактнее текстового.

  4. HPACK сжимает заголовки. Использует статический и динамический словари.

  5. gRPC использует POST для всех вызовов. Даже для получения данных (unary). Путь содержит сервис и метод: /:service/:method.

  6. Статус gRPC передаётся в трейлерах, а не в заголовках.

  7. Для продакшена нужен TLS. Браузеры не поддерживают HTTP/2 без TLS.

Проверка знаний

Вопрос 1 из 4
Какой транспортный протокол лежит в основе gRPC?
Что даёт HTTP/2 gRPC?
Какую проблему HTTP/1.1 помогает уменьшить HTTP/2?
Что такое HPACK в контексте HTTP/2?

Вопросы, где были ошибки