Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Як cluster допомагає масштабувати застосунок?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)`cluster` створює по одному воркеру на кожне ядро CPU, кожен зі своїм event loop і пам'яттю, і розподіляє запити між ними Round Robin - так одноядерний за замовчуванням Node.js навантажує весь багатоядерний сервер. **Ключове:** якщо воркер падає, master помічає це через подію `exit` і одразу створює новий - масштабування й відмовостійкість в одному механізмі.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## 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 використовувати **всі доступні ядра процесора**, > створюючи пул воркерів, які **паралельно обробляють запити**. > > Це забезпечує **масштабованість, відмовостійкість і високу продуктивність** - > без зміни логіки застосунку.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.