Learning Platform
Глоссарий Troubleshooting
Урок 03.01 · 18 мин
Начальный
HTTPTCPQUICHTTP/2HTTP/3Networking

Что такое HTTP — текстовый протокол поверх TCP

HTTP (Hypertext Transfer Protocol) — это правила, по которым ваш браузер, ваш Python-скрипт и ваш мобильный телефон общаются с серверами в интернете. Когда вы открываете github.com, происходит около двадцати HTTP-запросов: за HTML, за CSS, за JS, за картинками, за API-ответами. Когда ваш ETL-скрипт тянет данные из API партнёра, он тоже говорит HTTP.

В этом уроке разберём, что такое HTTP на самом деле: какой это протокол, как он лежит поверх TCP, чем отличаются версии 1.1, 2 и 3, и почему «stateless» — это не баг, а главная архитектурная фича.


История: от документов к API

HTTP родился в 1991 году в CERN. Тим Бернерс-Ли проектировал «World Wide Web» — систему гипертекстовых документов, в которой можно ссылаться с одного документа на другой. Нужен был протокол передачи этих документов. Так появился HTTP/0.9 — однострочный протокол, который умел только одно: вернуть HTML по запросу.

Эволюция HTTP -- от документов к мультимедиа и API
1991HTTP/0.9. Один метод (GET), без заголовков, без статус-кодов. Только HTML
1996HTTP/1.0. Заголовки, статус-коды, методы POST/HEAD. Появилась возможность передавать не только HTML
1997-99HTTP/1.1. Persistent connections (keep-alive), chunked encoding, кэширование, host-header (один сервер обслуживает несколько сайтов)
2015HTTP/2. Бинарный формат, мультиплексирование (несколько запросов в одном TCP), header compression (HPACK), server push
2022HTTP/3. Поверх QUIC (UDP), решает head-of-line blocking, быстрый handshake, лучше работает на мобильных сетях

Ключевой момент: HTTP/1.1 — это до сих пор основа большинства интернета. По данным Cloudflare на 2026 год, около 55% запросов в мире идут по HTTP/2, около 30% — по HTTP/3, и около 15% — всё ещё HTTP/1.1. При этом семантика везде одинаковая: методы, статус-коды, заголовки. Версия меняет только то, как байты передаются по проводам. Поэтому, изучив HTTP/1.1, вы понимаете 95% всего, что нужно для работы.


HTTP — это текстовый протокол (в версии 1.1)

В HTTP/1.1 запросы и ответы — это обычный ASCII-текст, который можно прочитать глазами. Это огромное преимущество для отладки: вы открываете curl -v, видите буквально, что улетело на сервер, что вернулось — и без специальных тулзов понимаете происходящее.

Вот как выглядит самый простой HTTP-запрос:

GET /get HTTP/1.1
Host: httpbin.org
Accept: */*
User-Agent: curl/8.4.0

И ответ от сервера:

HTTP/1.1 200 OK
Date: Thu, 14 May 2026 10:30:45 GMT
Content-Type: application/json
Content-Length: 312

{
  "args": {},
  "headers": {
    "Host": "httpbin.org",
    "User-Agent": "curl/8.4.0"
  },
  "url": "https://httpbin.org/get"
}

Заметьте структуру: первая строка (request-line или status-line), потом заголовки в формате Имя: Значение по одному на строку, потом пустая строка, потом опционально тело. Это и есть HTTP — никакой бинарщины, никаких магических констант.

NOTE

В HTTP/2 и HTTP/3 формат бинарный — для производительности. Но семантика та же: методы, статус-коды, заголовки. И что важно: curl -v всё равно покажет вам всё в текстовом виде, потому что библиотека сама декодирует бинарный поток обратно в текст для отладки.


HTTP лежит поверх TCP (в большинстве случаев)

HTTP — это протокол прикладного уровня (Layer 7 в OSI). Он не передаёт байты по сети сам — он использует для этого транспортный протокол. В версиях HTTP/1.1 и HTTP/2 — это TCP. В HTTP/3 — QUIC, который под капотом UDP.

Модель OSI: зачем нужны слои TCP 3-way handshake: как устанавливается соединение
Стек протоколов: HTTP в контексте TCP/IP
HTTPПрикладной протокол. Знает про методы, заголовки, ресурсы. Не знает про IP-адреса и пакеты
TLS (HTTPS)Шифрование транспортного уровня. Опционально, но в 2026 году de facto обязательно
TCPГарантированная доставка байт-за-байтом, в правильном порядке. Делает 3-way handshake перед началом передачи
UDPБез гарантий доставки, без подтверждений. Зато быстрее. Используется в HTTP/3 как фундамент QUIC
IPМаршрутизация пакетов между узлами. Знает про IP-адреса (1.2.3.4), не знает про порты и приложения

Что делает TCP под капотом, упрощённо:

  1. 3-way handshake. Клиент шлёт SYN, сервер отвечает SYN-ACK, клиент шлёт ACK. После этого соединение установлено и можно передавать данные. Это занимает 1 RTT (round-trip time) — типично 30-100 мс.
  2. Reliable delivery. TCP гарантирует, что байты дойдут в том порядке, в котором были отправлены. Если пакет потерялся — TCP сам перешлёт.
  3. Flow control. Если получатель не успевает обрабатывать данные — TCP замедлит отправителя.
  4. Congestion control. Если в сети загруженность — TCP уменьшит скорость отправки.

Для HTTP это значит: отправил запрос — гарантированно получишь ответ (если сервер вообще ответит). Не нужно проверять контрольные суммы и переотправлять — TCP делает это сам.

# Посмотреть TCP-соединения вашей машины:
# macOS/Linux:
netstat -an | grep ESTABLISHED | head
# или (более современный):
lsof -i -P -n | grep ESTABLISHED | head

# Это покажет открытые TCP-соединения, в том числе HTTP-сессии браузера и приложений

HTTPS — это HTTP внутри TLS

Вы видите в адресной строке браузера https:// — это HTTP внутри TLS (Transport Layer Security). TLS добавляет три вещи:

  1. Шифрование. Никто между клиентом и сервером не прочитает содержимое запроса.
  2. Аутентификация сервера. Сертификат подтверждает, что вы реально говорите с github.com, а не с подменённым сервером.
  3. Целостность. Никто не может изменить запрос или ответ по дороге незаметно.

Деталям TLS посвящён модуль 3. Пока важно понимать: HTTPS — это не «другой протокол», это HTTP, обёрнутый в TLS-туннель. Семантика, методы, статус-коды — всё то же самое.

# Сравните вывод этих двух команд -- вы увидите тот же HTTP-обмен,
# только во втором случае с TLS-handshake перед HTTP:
curl -v http://httpbin.org/get 2>&1 | head -20
curl -v https://httpbin.org/get 2>&1 | head -30

HTTP/2: мультиплексирование и бинарный формат

HTTP/1.1 имеет одно неудобное свойство: на одно TCP-соединение в одно время можно отправить ровно один запрос и ждать ответа. Если страница хочет загрузить 50 ресурсов (CSS, JS, картинки), браузер открывает несколько TCP-соединений параллельно (обычно 6 на домен). Но это не масштабируется бесконечно — TCP-соединения тяжелы для сервера.

HTTP/2 решает это через мультиплексирование: одно TCP-соединение, но несколько одновременных «потоков» (streams) внутри него. Браузер шлёт 50 запросов параллельно — сервер отвечает в любом порядке.

HTTP/1.1 vs HTTP/2: связи между запросами
HTTP/1.1Один TCP -- один запрос в момент времени. Нужно много соединений для параллельных запросов. Head-of-line blocking на уровне HTTP
HTTP/2Одно TCP-соединение, несколько streams внутри. Запросы и ответы могут приходить в любом порядке, мультиплексируются на уровне HTTP
Бинарный фреймHTTP/2 не текст: данные разбиты на фреймы (HEADERS, DATA, SETTINGS и др.). Удобно для парсинга машинами, неудобно для глаз
HPACK compressionЗаголовки сжимаются через HPACK -- словарь типичных пар заголовок/значение. Существенно уменьшает overhead на повторяющихся headers

Однако у HTTP/2 есть проблема: head-of-line blocking на уровне TCP. Если один TCP-пакет потерялся, TCP не отдаёт следующие пакеты приложению, пока не получит потерянный. Все streams в этом TCP-соединении ждут. Для HTTP/1.1 это не страшно (всё равно один запрос), а для мультиплексированного HTTP/2 — больно.


HTTP/3: QUIC поверх UDP

HTTP/3 и QUIC: мультиплексирование без HoL blocking

HTTP/3 решает HoL blocking радикально — отказывается от TCP. Под капотом теперь QUIC (Quick UDP Internet Connections) — протокол поверх UDP, в котором мультиплексирование сделано на уровне транспорта. Если один пакет потерян — это влияет только на тот stream, к которому он относится. Остальные streams продолжают работать.

HTTP/3 + QUIC -- мультиплексирование без HoL blocking
HTTP/3Семантика та же: методы, статус-коды, заголовки. Изменилось только то, что под капотом
QUICТранспортный протокол с мультиплексированием. Каждый stream независимый -- потеря пакета не блокирует другие streams. Встроенный TLS 1.3
UDPНизкоуровневый транспорт без гарантий. Все гарантии теперь делает QUIC сам

Дополнительные плюсы QUIC:

  • 0-RTT handshake. Если вы уже подключались к серверу, повторное соединение занимает 0 round-trips (TCP+TLS традиционно — 2-3 RTT).
  • Connection migration. Если вы переключились с Wi-Fi на 4G — QUIC-соединение продолжит работать. TCP бы разорвалось.
  • Лучшая производительность на мобильных. Высокий jitter и потери на 4G/5G — QUIC справляется лучше.

Большинство современных серверов (Cloudflare, Google, Facebook) поддерживают HTTP/3, и браузеры автоматически переключаются. Для Junior DE это значит: пишете requests.get(url) — библиотека на стороне Python пока работает по HTTP/1.1 или HTTP/2 (requests не поддерживает HTTP/3 на май 2026). httpx тоже HTTP/2-only. HTTP/3 поддерживают aioquic и h3 — экспериментальные библиотеки.


Stateless: главная архитектурная фича HTTP

Вторая важнейшая характеристика HTTP — statelessness. Каждый запрос полностью независим от предыдущих. Сервер ничего не помнит между запросами — каждый запрос должен содержать всю информацию для обработки.

REST поверх HTTP — архитектурный стиль, а не протокол

Звучит странно: «но как же тогда работает авторизация? Каким образом я остаюсь залогинен на сайте?» Ответ: на каждом запросе клиент сам передаёт всё нужное. Cookie, Bearer-токен, session ID — это не «состояние сервера», это идентификатор, который клиент шлёт на каждом запросе.

Stateless: каждый запрос независим
Запрос 1GET /api/users/me с Authorization: Bearer abc123. Сервер не помнит вас -- он каждый раз заново валидирует токен
СерверОбработал, ответил. Забыл о вас полностью
Запрос 2GET /api/orders с Authorization: Bearer abc123. Снова валидируется токен. Сервер не помнит, что это вы только что были
СерверТот же сервер или совсем другой инстанс -- для HTTP это неважно. Stateless = horizontally scalable

Польза statelessness — фундаментальная:

  1. Horizontal scaling. Запрос можно отправить на любой из 100 серверов в кластере — все равноправны, ни один не «помнит» вас. Балансировщик нагрузки тупо распределяет запросы по round-robin.
  2. Простая отладка. Чтобы воспроизвести баг, достаточно того же запроса. Не нужно «восстанавливать сессию».
  3. Кэширование. Промежуточные прокси и CDN могут кэшировать ответы. Это работает, потому что запрос самодостаточен.

Минус: каждый запрос несёт overhead (заголовки, токен, cookies). Это решается компрессией заголовков (HTTP/2 HPACK, HTTP/3 QPACK) и persistent connections.

WARNING

‘Сессия’ и ‘session ID в cookie’ — это иллюзия statefulness над stateless протоколом. Сервер не хранит вашу сессию в TCP-соединении. Он хранит её в Redis/БД, а cookie — это ключ. Каждый запрос вы шлёте этот ключ заново.


Реальный пример: что происходит при curl https://api.github.com/users/torvalds

Соберём всё вместе. Вот что физически происходит, когда вы выполняете эту команду:

Полный цикл одного HTTPS-запроса
1. DNS lookupРезолвим api.github.com -> IP-адрес. Через системный DNS (/etc/resolv.conf или DoH). ~10-50 мс
2. TCP handshake3-way handshake: SYN, SYN-ACK, ACK. ~30-100 мс в зависимости от расстояния до сервера
3. TLS handshakeОбмен сертификатами, согласование шифров, генерация session keys. TLS 1.3 -- ~30-50 мс. TLS 1.2 -- ~80-150 мс
4. HTTP requestОтправляется HTTP-запрос внутри TLS-туннеля. Текстовый запрос с заголовками
5. Server processingGitHub принимает запрос, обрабатывает (валидирует, ходит в БД, формирует JSON). ~50-200 мс
6. HTTP responseСервер шлёт ответ внутри того же TLS-туннеля. Заголовки + JSON-тело

Итого: ~150-500 мс на один запрос с нуля. Если вы шлёте 100 таких запросов — это 15-50 секунд тупого времени на handshake’ах. Поэтому в production HTTP-клиенты переиспользуют TCP-соединения (connection pooling, keep-alive). Подробно — в модуле 6.


Попробуй сам

Если установлен curl, посмотрите все слои HTTP-запроса своими глазами:

# Посмотреть полный verbose вывод HTTPS-запроса:
curl -v https://httpbin.org/get 2>&1 | head -50

# Посмотреть TLS-детали отдельно:
curl --trace-time -v https://httpbin.org/get 2>&1 | grep -E '^(TLS|SSL|<|>)'

# Узнать, по какой версии HTTP идёт связь (httpbin поддерживает HTTP/1.1 и HTTP/2):
curl -I -w 'HTTP version: %{http_version}\n' https://httpbin.org/get

# Сравнить с GitHub (поддерживает HTTP/2):
curl -I -w 'HTTP version: %{http_version}\n' https://api.github.com

# Посмотреть, поддерживает ли сервер HTTP/3 (через alt-svc заголовок):
curl -sI https://www.google.com | grep -i alt-svc
# Что-то вроде: alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000

Если в выводе curl -v посмотреть строки, начинающиеся с > — это что вы отправили. Со < — что вернулось. Это и есть raw HTTP-обмен в текстовом виде. На следующем уроке мы разберём этот формат до каждой строчки.


Проверка знанийKnowledge check
Junior спрашивает: 'Если HTTP stateless, то как сервер понимает, что я залогинен? Я же ввожу пароль один раз, а потом могу делать сотни запросов'
ОтветAnswer
Сервер не 'помнит' вас в смысле stateful-сессии в памяти процесса. Когда вы залогинились, сервер выдал вам какой-то идентификатор (session ID в cookie, или JWT-токен в Authorization-заголовке). Этот идентификатор клиент (браузер или ваш HTTP-клиент) сохраняет и шлёт ОБРАТНО на каждом следующем запросе. Сервер на каждом запросе заново смотрит этот ID, валидирует его (для session ID -- лезет в Redis или БД проверить, что сессия активна; для JWT -- проверяет подпись и срок действия), и решает, что да, это вы. Stateless здесь означает не 'сервер забывает пользователей', а 'каждый HTTP-запрос содержит всю информацию для своей обработки' -- клиент сам несёт идентификатор на каждом запросе. Это позволяет балансировщику отправить ваш запрос на любой из десятков серверов в кластере -- все они одинаково смогут провалидировать ваш токен. В этом фундаментальная польза statelessness: horizontal scalability.

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 5. Что значит, что HTTP -- 'stateless' протокол?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 5