Skip to main content

Як cluster допомагає масштабувати застосунок?

1. Проблема однопоточності Node.js

Node.js за своєю природою однопоточний - увесь JavaScript виконується в одному потоці з одним event loop.

Це означає:

  • один Node.js-застосунок може використовувати лише одне ядро CPU;
  • якщо сервер багатоядерний (а таких більшість) - решта ядер простоюють;
  • за великої кількості запитів event loop може перевантажуватися, і сервер починає "гальмувати".

2. Що робить cluster

Модуль cluster дозволяє запустити кілька копій (воркерів) твого застосунку

  • за кількістю ядер CPU - і розподіляти між ними навантаження.

Простіше кажучи:

cluster перетворює один сервер Node.js на пул незалежних процесів, що працюють паралельно, кожен - зі своїм event loop і пам'яттю.

3. Як це працює

Архітектура cluster:

javascript
┌───────────────────────┐ Master (головний процес)- слухає порт (наприклад 3000)- створює воркерів (через fork)└──────────────┬────────┘ ┌───────────┴───────────┐ │ │ │ ▼ ▼ ▼ Worker 1 Worker 2 Worker 3 ... Worker N (порт 3000) (порт 3000) (порт 3000)

Кожен воркер:

  • це окремий процес Node.js;
  • має свій event loop, свій runtime, свою пам'ять;
  • слухає той самий порт, що й решта.

Головний процес (master):

  • приймає вхідні з'єднання,
  • розподіляє запити між воркерами (за принципом Round Robin),
  • стежить за станом воркерів і може перезапускати їх у разі збою.

4. Приклад масштабування з cluster

javascript
import cluster from 'cluster'; import http from 'http'; import os from 'os'; if (cluster.isPrimary) { const numCPUs = os.cpus().length; console.log(`Головний процес ${process.pid}, запускаємо ${numCPUs} воркерів...`); // Запускаємо воркерів за кількістю ядер for (let i = 0; i < numCPUs; i++) cluster.fork(); cluster.on('exit', (worker) => { console.log(`Воркер ${worker.process.pid} завершився. Перезапуск...`); cluster.fork(); }); } else { // Кожен воркер створює свій HTTP-сервер http.createServer((req, res) => { res.end(`Відповідь від воркера ${process.pid}\n`); }).listen(3000); console.log(`Воркер ${process.pid} запущено`); }

На 8-ядерному процесорі створиться 8 воркерів, і всі вони слухатимуть порт 3000, розподіляючи навантаження.

5. Як cluster підвищує масштабованість

ПроблемаЩо робить cluster
Node.js використовує лише 1 ядроСтворює процеси за кількістю ядер
Один event loop - вузьке місцеКілька event loop (по 1 на воркер)
Один процес може впастиГоловний процес перезапускає воркер
Зростання трафіку збільшує навантаженняЗапити розподіляються по воркерах
Обмеження на пам'ять і GCКожен воркер має свою heap

Тобто cluster вирішує проблему масштабування по CPU ("vertical scaling") - максимально завантажує всі ядра процесора.

6. Переваги використання cluster

ПеревагаОпис
Багатопроцесорна продуктивністьЗастосунок обробляє більше запитів одночасно
Ізоляція помилокПадіння одного воркера не впливає на решту
Автоматичний перезапускКластер може автоматично відродити воркер
Розподіл навантаженняУсі воркери слухають один порт, навантаження рівномірне
Сумісність з Express / Fastify / NestJSМожна просто "обгорнути" наявний сервер
Готовність до продакшенуВикористовується всередині PM2 та інших менеджерів процесів

7. Приклад: навантажувальне тестування

Без cluster (1 процес, 1 ядро):

  • сервер витримує, скажімо, 1000 запитів/сек.

З cluster (8 воркерів на 8 ядер):

  • кожен воркер обробляє ~1000 запитів/сек,
  • загальний throughput приблизно 8000 запитів/сек.

8. Масштабування + відмовостійкість

cluster не лише пришвидшує, а й робить систему стійкою:

  • якщо один воркер завис чи впав → master помічає цю подію (exit);
  • створює новий воркер замість того, що впав;
  • сервер продовжує працювати без простою.

9. Як кластер використовується на практиці

Часто застосовується:

  • у продакшені серверів (Express, Fastify, NestJS);
  • у системах мікросервісів і REST API;
  • усередині менеджерів процесів - наприклад, PM2;
  • на балансувальниках WebSocket чи GraphQL-серверів.

PM2 під капотом використовує cluster:

javascript
pm2 start app.js -i max

⟶ автоматично створює стільки воркерів, скільки є ядер CPU.

10. Що важливо пам'ятати

  • Воркери не діляться пам'яттю → дані потрібно синхронізувати через IPC чи Redis.
  • Для WebSocket-з'єднань краще використовувати sticky sessions, щоб одне з'єднання лишалося на одному воркері.
  • За масштабування на кілька машин потрібен зовнішній балансувальник (Nginx, HAProxy, AWS ELB).

Підсумок

Критерійcluster
Що робитьЗапускає кілька копій застосунку на всіх ядрах CPU
Як масштабуєРозподіляє запити між процесами
Де застосовуєтьсяСервери, API, продакшн-застосунки
Тип масштабуванняВертикальне (по ядрах CPU)
Обмін данимиЧерез IPC (Inter-Process Communication)
ПеревагиПродуктивність, стійкість, fault-tolerance

Висновок:

Модуль cluster дозволяє Node.js використовувати всі доступні ядра процесора, створюючи пул воркерів, які паралельно обробляють запити.

Це забезпечує масштабованість, відмовостійкість і високу продуктивність - без зміни логіки застосунку.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.