open atlas
↑ К треку
Архитектура бэкенда BE · 01 · 01

Путь запроса: семь остановок от сокета до ответа

Каждый HTTP-запрос проходит один и тот же путь — accept, парсинг, маршрутизация, middleware, обработка, сериализация, drain. Знание карты подсказывает, где прячутся задержка, сбой и уязвимость.

BE Junior ◷ 10 min
Уровень
ОсновыJuniorMiddleSenior
Уже знаешь этот юнит? Пройди быструю проверку за минуту →

Пользователь нажимает «Сохранить». Через 180 мс он видит зелёную галочку. За эти 180 мс запрос прошёл через балансировщик, полежал в очереди ядра, был разобран байт за байтом, сопоставлен с таблицей маршрутов, прошёл стопку middleware, выполнил ваш обработчик, был сериализован в JSON и отправлен обратно потоком — пройдя семь разных стадий, у каждой свой режим отказа. Большинство инженеров назовут обработчик. Немногие назовут остальные шесть.

Семь остановок

Уберите фреймворк — и любой серверный запрос имеет одну и ту же форму. Названия отличаются в Express, Spring, net/http Go и Rails, но стадии — нет:

  1. Accept — ядро завершает TCP-рукопожатие и передаёт процессу установленный сокет.
  2. Парсинг — байты из сокета превращаются в строку запроса, заголовки и тело.
  3. Маршрутизация — метод и путь сопоставляются с одним обработчиком.
  4. Middleware — сквозные слои выполняются по порядку: auth, логирование, парсинг тела, rate limiting.
  5. Обработка — выполняется бизнес-логика, обычно в ожидании БД или другого сервиса.
  6. Сериализация — результат становится байтами: JSON, HTML, поток.
  7. Drain — ответ записывается в сокет, который может быть медленнее обработчика, и соединение удерживается (keep-alive) или закрывается.

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

Перед остановкой 1 обычно стоит reverse proxy (обратный прокси-сервер) (nginx, Envoy, облачный балансировщик): он терминирует TLS, выбирает бэкенд и может буферизовать весь запрос. Этот прокси — отдельный жизненный цикл со своими семью остановками на другой стороне.

Где прячется каждая проблема

Карта важна потому, что каждый класс ошибок живёт на конкретной остановке. Отладка вслепую — это проверка всех семи; отладка с картой — это прыжок к одной.

СимптомПодозреваемая остановка
Соединения отклоняются под нагрузкойAccept — переполнилась очередь accept в ядре
431 / 400 на больших cookieПарсинг — превышен буфер заголовков
Срабатывает не тот обработчикМаршрутизация — пересекающиеся шаблоны путей
Обход auth на одном эндпоинтеMiddleware — порядок: обработчик сработал до слоя auth
p50 быстрый, p99 ужасныйОбработка — медленная нижестоящая зависимость
Высокий CPU на больших ответахСериализация — JSON.stringify на огромном объекте
Память растёт на медленных клиентахDrain — backpressure проигнорирован, ответ буферизован в RAM

Задержка суммируется, а не локализуется

Полное время запроса — это сумма всех остановок плюс время ожидания в очередях между ними. Обработчик, выполняющийся за 5 мс, всё равно может дать ответ за 200 мс, если очередь accept была глубокой, тело буферизовал прокси, а клиент читал ответ медленно. Поэтому «код быстрый» и «эндпоинт медленный» истинны одновременно — они описывают разные остановки.

Senior-навык — не запоминание семи названий. Это рефлекс: по этому симптому — какая остановка? Когда увидишь всплеск p99 или лавину отклонённых соединений, первый вопрос должен быть «на какой остановке?», а не «что делает код?». Дальше юнит проходит каждую остановку в продакшн-деталях.

Викторина

У сервиса обработчик 3 мс, но под нагрузкой пользователи видят ответы по 250 мс. Какие остановки наиболее вероятны?

Викторина

Почему reverse proxy перед сервером приложений важен для жизненного цикла запроса?

Расставь шаги по порядку

Расставьте семь остановок запроса в порядке их прохождения:

  1. 1 Accept — ядро передаёт процессу установленный сокет
  2. 2 Парсинг — байты становятся строкой запроса, заголовками, телом
  3. 3 Маршрутизация — метод и путь сопоставлены с обработчиком
  4. 4 Middleware — auth, логирование, парсинг тела выполняются по порядку
  5. 5 Обработка — выполняется бизнес-логика, ждёт зависимости
  6. 6 Сериализация — результат становится байтами
  7. 7 Drain — ответ записан в сокет, соединение удержано или закрыто
Вспомните перед уходом
  1. 01
    Назовите семь остановок жизненного цикла запроса по порядку и по одной проблеме на каждой.
  2. 02
    Почему у сервиса может быть обработчик 3 мс, но время ответа 250 мс?
  3. 03
    Что добавляет reverse proxy перед семью остановками и почему у него свой жизненный цикл?
Итог

Любой серверный HTTP-запрос проходит одни и те же семь остановок: accept (ядро передаёт сокет), парсинг (байты становятся запросом), маршрутизация (путь к обработчику), middleware (сквозные слои по порядку), обработка (бизнес-логика), сериализация (результат в байты) и drain (запись в сокет, keep-alive или закрытие). Reverse proxy спереди добавляет свою копию этого цикла. Полная задержка — сумма по остановкам плюс ожидание в очередях, поэтому быстрый обработчик всё равно может дать медленный эндпоинт. Каждый класс ошибок живёт на конкретной остановке — ценность карты в рефлексе прыжка к нужной. Теперь, когда встретишь сервис, который «медленный, но код в порядке», первый шаг — назвать остановку, а не читать обработчик. Следующий урок углубляется в первые две остановки: как ядро принимает соединение и как сырые байты становятся разобранным запросом.

Практика

Начни сверху. Задачи идут от простого к сложному: вспомнить факт, применить к случаю, затем senior-уровень. Открой, попробуй, потом открой ответ.

вспомнитьприменитьуглубить0 из 5 завершено
Связанные уроки
встречается в188

Что-то непонятно?

Задай вопрос по этому уроку. Вопросы анонимны и попадают напрямую автору — урок станет лучше.

Примени это

Примени этот урок в реальном проекте.

хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.