awesome-everything EN
↑ Обратно к восхождению

Архитектура бэкенда

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

Суть Каждый HTTP-запрос проходит один и тот же путь — accept, парсинг, маршрутизация, middleware, обработка, сериализация, drain. Знание карты подсказывает, где прячутся задержка, сбой и уязвимость.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на junior-высоте — поверхность
◷ 10 min

Пользователь нажимает «Сохранить». Через 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-навык — не запоминание семи названий. Это рефлекс: по этому симптому — какая остановка? Дальше юнит проходит каждую остановку в продакшн-деталях.

Викторина

У сервиса обработчик 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 спереди добавляет свою копию этого цикла. Полная задержка — сумма по остановкам плюс ожидание в очередях, поэтому быстрый обработчик всё равно может дать медленный эндпоинт. Каждый класс ошибок живёт на конкретной остановке — ценность карты в рефлексе прыжка к нужной. Следующий урок углубляется в первые две остановки: как ядро принимает соединение и как сырые байты становятся разобранным запросом.

Связанные уроки
встречается в185
Продолжить восхождение ↑Accept и парсинг: от очереди ядра до типизированного запроса
хоткеи развернуть
поиск
K
пред. пьеса
k
след. пьеса
j
тиры
t
это меню
?
sources3
expand
  1. 01
  2. 02
  3. 03

Trademarks belong to their respective owners. Editorial reference only.