← Назад к вопросам
В чем разница между Worker Threads и Cluster в Node.js?
2.0 Middle🔥 91 комментариев
#Node.js и JavaScript
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Worker Threads и Cluster — это два разных способа создания параллелизма в Node.js. Они решают разные задачи и имеют разные архитектурные подходы.
Worker Threads
Worker Threads позволяют выполнять JavaScript код в отдельных потоках внутри одного процесса.
const {Worker} = require('worker_threads');
const worker = new Worker('./worker.js');
worker.on('message', (msg) => {
console.log('From worker:', msg);
});
worker.postMessage('Hello Worker');
// worker.js
const {parentPort} = require('worker_threads');
parentPort.on('message', (msg) => {
console.log('From parent:', msg);
parentPort.postMessage('Response from worker');
});
Характеристики:
- Общая память между потоками
- Малый оверхед (меньше памяти)
- Для CPU-интенсивных задач
- Одно Node.js выполнение
Cluster
Cluster создает несколько отдельных Node.js процессов (воркеров).
const cluster = require('cluster');
const os = require('os');
const http = require('http');
if (cluster.isMaster) {
const numCPUs = os.cpus().length;
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker) => {
console.log(`Worker ${worker.process.pid} died`);
cluster.fork(); // Перезапуск
});
} else {
http.createServer((req, res) => {
res.writeHead(200);
res.end(`Worker ${process.pid}`);
}).listen(3000);
}
Характеристики:
- Отдельные процессы (каждый со своей памятью)
- Большой оверхед (больше памяти)
- Для I/O-интенсивных задач
- Встроенная поддержка load balancing
- Auto-restart при сбое
Сравнение
| Параметр | Worker Threads | Cluster |
|---|---|---|
| Тип | Потоки в одном процессе | Отдельные процессы |
| Память | Общая, малый оверхед | Отдельная, большой оверхед |
| Общее состояние | Может быть (осторожно!) | Нет (отдельная память) |
| Коммуникация | postMessage (быстро) | IPC (медленнее) |
| Изоляция | Слабая | Сильная |
| Использование | CPU-задачи | Web-сервер (I/O) |
| Restart | Ручной | Автоматический |
Worker Threads для CPU-интенсивных задач
const {Worker} = require('worker_threads');
// Основной поток
const http = require('http');
http.createServer((req, res) => {
if (req.url === '/calculate') {
// Создать worker для тяжелых вычислений
const worker = new Worker('./calculator.js');
worker.on('message', (result) => {
res.writeHead(200);
res.end(`Result: ${result}`);
worker.terminate();
});
worker.postMessage(1000000); // Отправить данные
} else {
res.writeHead(200);
res.end('OK');
}
}).listen(3000);
// calculator.js (Worker)
const {parentPort} = require('worker_threads');
parentPort.on('message', (num) => {
let result = 0;
for (let i = 0; i < num; i++) {
result += Math.sqrt(i);
}
parentPort.postMessage(result);
});
Cluster для Web-сервера
const cluster = require('cluster');
const os = require('os');
const http = require('http');
const {Server} = require('net');
if (cluster.isMaster) {
const numCPUs = os.cpus().length;
console.log(`Master ${process.pid} running`);
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code) => {
console.log(`Worker ${worker.process.pid} died`);
if (!worker.exitedAfterDisconnect) {
console.log('Worker crashed, creating new one');
cluster.fork();
}
});
} else {
http.createServer((req, res) => {
// Каждый worker обрабатывает запросы
res.writeHead(200);
res.end(`Handled by ${process.pid}`);
}).listen(3000);
console.log(`Worker ${process.pid} started`);
}
Когда использовать Worker Threads
// Тяжелые вычисления, обработка данных
const {Worker} = require('worker_threads');
// Парсинг больших JSON
const parseWorker = new Worker('./json-parser.js');
// Криптография
const cryptoWorker = new Worker('./crypto.js');
// Image processing
const imageWorker = new Worker('./image-processor.js');
Когда использовать Cluster
// Web-server, который обрабатывает много I/O запросов
const cluster = require('cluster');
if (cluster.isMaster) {
// Автоматическое распределение нагрузки
for (let i = 0; i < 4; i++) {
cluster.fork();
}
}
// Каждый воркер обрабатывает I/O независимо
app.get('/', async (req, res) => {
const data = await db.query('...');
res.json(data);
});
Гибридный подход
const cluster = require('cluster');
const {Worker} = require('worker_threads');
const os = require('os');
if (cluster.isMaster) {
const numCPUs = os.cpus().length;
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
} else {
const http = require('http');
http.createServer((req, res) => {
if (req.url === '/heavy') {
// Использовать Worker для тяжелой работы
const worker = new Worker('./heavy-task.js');
worker.on('message', (result) => {
res.end(result);
});
} else {
res.end('OK');
}
}).listen(3000);
}
Примеры использования
Worker Threads для асинхронной обработки
const pWorker = require('piscina'); // Пул воркеров
const pool = new pWorker({filename: './worker.js'});
app.post('/process', async (req, res) => {
try {
const result = await pool.run(req.body);
res.json(result);
} catch (e) {
res.status(500).json({error: e.message});
}
});
Cluster для автомасштабирования
const cluster = require('cluster');
let workerCount = os.cpus().length;
let activeWorkers = 0;
if (cluster.isMaster) {
for (let i = 0; i < workerCount; i++) {
cluster.fork();
}
// Мониторинг и динамическое масштабирование
setInterval(() => {
const workers = Object.values(cluster.workers);
console.log(`Active workers: ${workers.length}`);
}, 10000);
}
Производительность
Worker Threads:
- Быстрая коммуникация
- Малая задержка
- Хороший для CPU-bound
Cluster:
- Медленнее (IPC)
- Изолированная память
- Хороший для I/O-bound
Вывод
- Worker Threads — для CPU-интенсивных задач в одном процессе
- Cluster — для масштабирования веб-серверов на несколько процессов
- Hybrid approach — использовать оба вместе для оптимальной производительности