Як 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:
┌───────────────────────┐
│ Master (головний процес) │
│ - слухає порт (наприклад 3000) │
│ - створює воркерів (через fork) │
└──────────────┬────────┘
│
┌───────────┴───────────┐
│ │ │
▼ ▼ ▼
Worker 1 Worker 2 Worker 3 ... Worker N
(порт 3000) (порт 3000) (порт 3000)Кожен воркер:
- це окремий процес Node.js;
- має свій event loop, свій runtime, свою пам'ять;
- слухає той самий порт, що й решта.
Головний процес (master):
- приймає вхідні з'єднання,
- розподіляє запити між воркерами (за принципом Round Robin),
- стежить за станом воркерів і може перезапускати їх у разі збою.
4. Приклад масштабування з cluster
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:
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 використовувати всі доступні ядра процесора, створюючи пул воркерів, які паралельно обробляють запити.Це забезпечує масштабованість, відмовостійкість і високу продуктивність - без зміни логіки застосунку.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.