Node.js є однопотоковим середовищем виконання, що означає, що воно може виконувати лише одне завдання одночасно. Проте, воно підтримує багатопотоковість за допомогою робочих потоків (worker threads).
Один із способів реалізації балансування навантаження на основі кількості ЦП за допомогою Express.js – це створення кількох робочих потоків і розподіл вхідних запитів між ними. Ось приклад реалізації:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
// Імпорт необхідних пакетів const cluster = require('cluster'); const os = require('os'); const express = require('express'); // Отримання кількості доступних ЦП const numCPUs = os.cpus().length; if (cluster.isMaster) { console.log(`Майстер-процес працює з PID ${process.pid}`); // Створення робочих потоків на основі кількості ЦП for (let i = 0; i < numCPUs; i++) { cluster.fork(); } // Слухання події запуску робочих потоків cluster.on('online', (worker) => { console.log(`Робочий процес ${worker.process.pid} працює`); }); // Слухання події виходу робочих потоків cluster.on('exit', (worker, code, signal) => { console.log(`Робочий процес ${worker.process.pid} вийшов з кодом ${code} і сигналом ${signal}`); console.log('Запуск нового робочого потоку'); cluster.fork(); }); } else { const app = express(); app.get('/', (req, res) => { res.send(`Привіт з робочого процесу ${process.pid}`); }); app.listen(3000, () => { console.log(`Робочий процес ${process.pid} прослуховує порт 3000`); }); } |
У цьому коді показано реалізацію балансування навантаження з використанням кластерів в Node.js. Майстер-процес створює робочі потоки на основі кількості доступних ЦП за допомогою методу os.cpus().length. Кожен робочий потік запускає свою власну копію програми Express.js і прослуховує окремий порт. Події запуску та виходу робочих потоків слухаються в майстер-процесі, що дозволяє замінити потік, що закінчився новим.
При виході (завершенні) робочого потоку (worker) з кодом cluster.on('exit', ...), майстер-процес реагує на цю подію і створює новий робочий потік за допомогою cluster.fork(). Таким чином, коли один з робочих потоків закінчує роботу, майстер-процес автоматично створює новий робочий потік, щоб замінити його. Це забезпечує безперервну роботу додатку, навіть якщо один з робочих потоків завершується.
Це важливо для забезпечення безперервності обробки запитів і балансування навантаження між робочими потоками. Коли один потік виходить, інший потік бере на себе обробку нових запитів. Таким чином, заміна вибувшого потоку новим дозволяє підтримувати стабільну роботу додатку і розподілення навантаження на доступні робочі потоки.