Перейти к содержанию

Производительность и кластеризация

Начало урока

Производительность и кластеризация

Один цикл событий быстр, но это по-прежнему одно ядро процессора. Вот как задействовать их все.

Главная идея: процесс Node.js выполняет ваш JavaScript в одном потоке, которым управляет единственный цикл событий. Эта модель превосходна для задач, ограниченных вводом-выводом, но у современного сервера много ядер процессора простаивает без дела. Кластеризация и менеджеры процессов позволяют запустить по одному процессу Node на каждое ядро, поставить перед ними балансировщик нагрузки и кратно увеличить пропускную способность — не переписывая логику приложения.
К концу урока вы сможете:
  • объяснить узкое место цикла событий и отличать задачи, ограниченные процессором, от задач ввода-вывода;
  • использовать модуль cluster, чтобы породить по одному воркеру на ядро и разделить слушающий порт;
  • описать, как распределяются входящие соединения (round-robin против операционной системы);
  • выбирать между cluster, worker_threads и горизонтальным масштабированием;
  • запускать боевые процессы под менеджером в стиле PM2 с перезагрузкой без простоя;
  • рассуждать о балансировке нагрузки, липких сессиях и общем состоянии между воркерами.

1. Узкое место цикла событий

Вы уже знаете, что цикл событий держит один поток занятым, никогда не блокируясь на вводе-выводе: пока запрос к базе данных или чтение файла в пути, цикл обслуживает другие колбэки. Но есть тонкий и критически важный нюанс — сам ваш JavaScript всё равно выполняется в одном потоке. Любой колбэк, тратящий реальное процессорное время (разбор огромного JSON, хеширование пароля с большим фактором стоимости, изменение размера изображения на чистом JS, плотный числовой цикл), захватывает поток в заложники. В это время ни один другой запрос не может быть обслужен, ни один таймер не сработает и ни один колбэк ввода-вывода не выполнится.

Именно это различие управляет каждым решением о масштабировании в Node:

  • Задачи, ограниченные вводом-выводом (ожидание диска, сети, базы данных) — цикл остаётся свободным, пока ожиданием занимается ОС. Один процесс с радостью обслуживает тысячи одновременных соединений.
  • Задачи, ограниченные процессором (вычисления, держащие поток занятым) — цикл заблокирован. Один медленный обработчик тормозит всех остальных клиентов, а рост числа одновременных запросов лишь ухудшает задержку.

Аналогия. Процесс Node — это один невероятно быстрый официант. Пока гости ждут кухню (ввод-вывод), официант снуёт между множеством столов, принимая заказы. Но как только вы просите этого единственного официанта лично приготовить блюдо за 20 минут (процессорная работа), все остальные столы ждут, каким бы быстрым он ни был. Это не решается просьбой двигаться быстрее — нужно нанять больше официантов. Это и есть кластеризация.

Обработчик, ограниченный процессором, не только замедляет сам себя; он раздувает задержку цикла событий для всех. Измерение этой задержки (например, через perf_hooks.monitorEventLoopDelay()) — стандартный способ обнаружить заблокированный цикл в бою.

Продолжите этот урок на YourAIZone

В полном уроке — объяснение целиком, разобранные примеры, частые ошибки, тесты с мгновенной проверкой и ИИ-репетитор. Начните сразу как гость или создайте аккаунт, чтобы сохранять прогресс.

В полном уроке

  • Объяснение целиком
  • Разобранные примеры
  • Частые ошибки и как их избежать
  • Тестовые вопросы: 15
  • ИИ-репетитор, который отвечает на вопросы по теме
  • Отслеживание прогресса для ученика, родителей и учителя