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

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

Async vs blocking: разморозь loop

Суть Практический проект — построй сервис, блокирующий собственный event loop, заинструментируй lag, затем вынеси CPU, ограничь fan-out и докажи возврат хвоста числами до/после.
Высота — путь к senior
НольJuniorMiddleSenior
Ты на senior-высоте — в орбите
◷ 240 min

Читать про замороженный loop — не то же, что вытащить сервис из него. Построй небольшой сервер, блокирующий себя тремя разными способами, посмотри, как таймаутит тривиальный health-check, затем применяй фиксы юнита — вынос, ограничение, backpressure — пока хвост не вернётся, с доказательством на каждом шаге.

Цель

Преврати ментальную модель юнита в воспроизводимый инженерный цикл: заинструментируй event-loop lag и хвост, воспроизведи самонанесённую заморозку, вынеси CPU-работу с loop, ограничь fan-out и подтверди числами до/после под идентичной нагрузкой.

Проект
0 из 7
Цель

Возьми намеренно блокирующий loop HTTP-сервис (свой или стартовый) с тривиальным эндпоинтом /health, загони его в event-loop lag и обвал хвоста, затем примени фиксы юнита — вынос CPU, ограничение конкурентности, соблюдение backpressure — чтобы держать p99 задержки /health ниже целевого, а event-loop delay p99 ниже ~50 мс под устойчивой нагрузкой, доказывая каждый шаг измерениями.

Требования
Критерии приёмки
  • Таблица до/после на route: event-loop delay p99, ELU, p99 и p99.9 запросов и конкурентность в полёте — измеренные под одной нагрузкой, не оценочные.
  • Демонстрация, что /health остаётся быстрым (p99 ниже целевого), пока каждого нарушителя долбят, доказывающая, что loop больше не head-of-line-блокирует весь процесс.
  • Event-loop delay p99 держится ниже ~50 мс под устойчивой нагрузкой, и сигнатура заморозки ушла из гистограммы lag.
  • Абзац разбора, называющий фикс для каждого нарушителя (async API vs worker thread vs лимит конкурентности vs backpressure) и почему он встал выше тюнинга UV_THREADPOOL_SIZE или добавления ядер.
Senior-стретч
  • Добавь ReDoS-нарушителя (regex с катастрофическим бэктрекингом на поле под контролем пользователя), покажи, как один подобранный запрос замораживает loop на секунды, затем почини безопасным regex / валидацией ввода / таймаутом матча и докажи, что заморозка ушла.
  • Добавь одностраничный on-call runbook: триаж по четырём панелям, вопрос «этот участок ограничен и быстр или может бежать десятки мс на большом вводе?», решение вынос-vs-чанк-vs-ограничение и чек-лист верификации.
  • Запусти сервис под cluster (или несколько инстансов за балансировщиком) и покажи, как «один loop — одно ядро» меняет точку насыщения и хвост под той же нагрузкой.
  • Воспроизведи ту же блокирующую нагрузку на втором рантайме (Go goroutines или Java virtual threads) и сравни, как идентичный CPU-участок и fan-out проявляются под вытесняющим многоядерным планировщиком.
Итог

Это цикл, который ты запустишь в каждом реальном инциденте заморозки: сначала заинструментируй event-loop delay и хвост, воспроизведи самонанесённую блокировку, затем чини на нужном слое — async API или worker thread для CPU-работы, лимит конкурентности для fan-out, backpressure через pipeline для потоков — никогда не больший пул libuv для JS CPU и никогда не больше ядер для одного loop. Подтверди числами до/после под идентичной нагрузкой, с тривиальным route /health как канарейкой. Сделав это раз на игрушечном сервисе, делаешь продакшен-версию мышечной памятью.

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

Trademarks belong to their respective owners. Editorial reference only.