← Назад к вопросам

Что такое Worker Threads в Node.js?

1.2 Junior🔥 231 комментариев
#Node.js и JavaScript

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Worker Threads — это встроенная в Node.js функция для запуска JavaScript кода в отдельных потоках. Это позволяет выполнять CPU-интенсивные операции без блокировки основного потока Event Loop.

Проблема, которую решают Worker Threads

Node.js однопоточный — весь код выполняется в одном потоке. Если выполнить CPU-интенсивную операцию, это заблокирует весь сервер:

// Плохо — блокирует Event Loop
const crypto = require('crypto');

app.get('/hash', (req, res) => {
  const hash = crypto.pbkdf2Sync('password', 'salt', 100000, 64, 'sha512');
  res.send(hash);
});

// Если запустить 10 запросов одновременно, они будут обработаны по очереди
// Каждый запрос ждёт 1 секунду = 10 запросов * 1 сек = 10 секунд для всех!

Worker Threads решают эту проблему:

const { Worker } = require('worker_threads');
const path = require('path');

app.get('/hash', (req, res) => {
  const worker = new Worker(path.join(__dirname, 'hash-worker.js'));
  
  worker.on('message', (hash) => {
    res.send(hash);
  });
  
  worker.on('error', (err) => {
    res.status(500).send(err.message);
  });
  
  worker.on('exit', (code) => {
    if (code !== 0) res.status(500).send('Worker stopped');
  });
});

// hash-worker.js
const crypto = require('crypto');
const { parentPort } = require('worker_threads');

const hash = crypto.pbkdf2Sync('password', 'salt', 100000, 64, 'sha512');
parentPort.postMessage(hash);

Основные концепции

Worker Thread запускается в отдельном потоке:

  • Не блокирует Event Loop
  • Не делится памятью (отдельный V8 instance)
  • Может быть переиспользован для нескольких задач
const { Worker } = require('worker_threads');

const worker = new Worker('./worker.js');

// Отправить сообщение worker'у
worker.postMessage({ data: 'hello' });

// Получить сообщение от worker'а
worker.on('message', (msg) => {
  console.log('Received:', msg);
});

// Завершить worker
worker.terminate();

Пример: Worker Pool

const { Worker } = require('worker_threads');
const path = require('path');

class WorkerPool {
  constructor(workerScript, poolSize = 4) {
    this.workers = [];
    this.taskQueue = [];
    this.poolSize = poolSize;
    
    for (let i = 0; i < poolSize; i++) {
      const worker = new Worker(workerScript);
      worker.busy = false;
      worker.on('message', () => {
        worker.busy = false;
        this.processQueue();
      });
      this.workers.push(worker);
    }
  }
  
  execute(data) {
    return new Promise((resolve, reject) => {
      const task = { data, resolve, reject };
      
      const freeWorker = this.workers.find(w => !w.busy);
      if (freeWorker) {
        this.runTask(freeWorker, task);
      } else {
        this.taskQueue.push(task);
      }
    });
  }
  
  runTask(worker, task) {
    worker.busy = true;
    worker.once('message', (result) => {
      task.resolve(result);
    });
    worker.once('error', (err) => {
      task.reject(err);
    });
    worker.postMessage(task.data);
  }
  
  processQueue() {
    if (this.taskQueue.length === 0) return;
    
    const freeWorker = this.workers.find(w => !w.busy);
    if (freeWorker) {
      const task = this.taskQueue.shift();
      this.runTask(freeWorker, task);
    }
  }
}

const pool = new WorkerPool(path.join(__dirname, 'heavy-task.js'), 4);

for (let i = 0; i < 10; i++) {
  pool.execute({ n: 1000000 })
    .then(result => console.log('Result:', result))
    .catch(err => console.error('Error:', err));
}

heavy-task.js (Worker Script)

const { parentPort } = require('worker_threads');

parentPort.on('message', (data) => {
  // CPU-интенсивная работа
  let sum = 0;
  for (let i = 0; i < data.n; i++) {
    sum += Math.sqrt(i);
  }
  
  parentPort.postMessage(sum);
});

Когда использовать Worker Threads

  • Криптография — хеширование паролей, подписание JWT
  • Обработка изображений — изменение размера, конвертация форматов
  • Математические расчёты — сложные вычисления
  • Сжатие данных — gzip, brotli
  • Парсинг больших файлов — JSON, CSV, XML
  • Machine Learning — инференс моделей

Не использовать для:

  • I/O операций (это не помогает)
  • Простых синхронных операций (overhead не стоит)
  • Сетевых запросов (используй async/await)

Worker Threads vs Cluster vs Process

Worker Threads:

  • Лёгкие потоки внутри одного процесса
  • Общая память (с ограничениями)
  • Для CPU-интенсивных задач
  • Маленький overhead

Cluster:

  • Отдельные Node.js процессы
  • Полная изоляция
  • Для балансировки нагрузки
  • Требует больше памяти

Child Process:

  • Любые программы (не только Node.js)
  • Для запуска скриптов на других языках

Пример: Хеширование пароля

const { Worker } = require('worker_threads');

app.post('/register', async (req, res) => {
  const worker = new Worker(`
    const { parentPort } = require('worker_threads');
    const crypto = require('crypto');
    
    parentPort.on('message', (password) => {
      const hash = crypto.pbkdf2Sync(password, 'salt', 100000, 64, 'sha512');
      parentPort.postMessage(hash.toString('hex'));
    });
  `, { eval: true });
  
  worker.postMessage(req.body.password);
  
  worker.on('message', async (hash) => {
    await User.create({ email: req.body.email, password: hash });
    res.send('Registered');
  });
});

Worker Threads — это мощный инструмент для оптимизации производительности Node.js приложений при работе с CPU-интенсивными операциями.