Загрузка…
Загрузка…
Node.js · middle · сложность 4
Как опытный технический интервьюер и преподаватель, я часто считаю, что понимание того, как Node.js обрабатывает параллелизм, является решающей концепцией. Давайте сломаем
child_process.fork()
и
worker_threads
для разгрузки ресурсоемких задач.
child_process.fork()
против.
worker_threads
Node.js известен своей однопоточной неблокируемой моделью ввода-вывода, основанной на цикле событий. Это отлично подходит для эффективной обработки множества одновременных сетевых подключений. Однако если ваше приложение столкнется с задачой, интенсивно использующей процессор (например, сложными вычислениями, обработкой изображений или тяжелыми манипуляциями с данными), оно блокирует одиночный цикл событий, в результате чего все ваше приложение перестанет отвечать до тех пор, пока задача не завершится.
Чтобы преодолеть это ограничение и разгрузить такие задачи, Node.js предоставляет два основных механизма:
child_process.fork()
и
worker_threads
. Хотя оба достигают определенной формы параллелизма, они делают это с помощью фундаментально разных механизмов.
child_process.fork()
: Отдельное офисное здание
child_process.fork()
создает новый, независимый процесс Node.js, который выполняется одновременно с родительским процессом. По сути, это похоже на запуск другого отдельного приложения Node.js.
Представьте, что ваше основное приложение Node.js — это штаб-квартира компании. Когда вы используете
fork()
, вы открываете совершенно новый отдельный филиал в другом городе. Этот новый офис имеет собственный персонал, собственные ресурсы (например, электричество и Интернет) и работает независимо. Если что-то пойдет не так в филиале, это не повлияет на штаб-квартиру.
Сообщения передаются туда и обратно явно.
child.send(message)
process.send(message)
child.on('message', handler)
или
process.on('message', handler)
.
fork()
:
fork()
может обрабатывать задачи, интенсивно использующие ЦП, он часто больше подходит для задач, требующих большого количества операций ввода-вывода (например, сетевых запросов, файловых операций или запросов к базе данных), которые могут выполняться независимо в фоновом режиме.
spawn()
для этого чаще встречается,
fork()
предназначен специально для сценариев Node.js.
fork()
):
Давайте представим себе задачу с интенсивным использованием процессора, например вычисление очень большого числа Фибоначчи.
**
fibonacci.js
(Сценарий дочернего процесса):**
// fibonacci.js
function calculateFibonacci(n) {
if (n {
if (message.type === 'calculateFibonacci') {
const result = calculateFibonacci(message.number);
// Send the result back to the parent process
process.send({ type: 'fibonacciResult', result: result });
}
});
console.log('Fibonacci child process started.');**
parent.js
(Основное приложение):**
// parent.js
const { fork } = require('child_process');
const path = require('path');
console.log('Main process started.');
// Create a new child process
const child = fork(path.join(__dirname, 'fibonacci.js'));
// Listen for messages from the child process
child.on('message', (message) => {
if (message.type === 'fibonacciResult') {
console.log(`Main process received Fibonacci result: ${message.result}`);
}
});
child.on('exit', (code, signal) => {
console.log(`Child process exited with code ${code} and signal ${signal}`);
});
// Simulate some other work in the main process
console.log('Main process doing other work...');
// Send a message to the child process to start calculation
const numberToCalculate = 400000; // A large number for a CPU-intensive task
console.log(`Main process sending request to calculate Fibonacci for ${numberToCalculate}...`);
child.send({ type: 'calculateFibonacci', number: numberToCalculate });
console.log('Main process continues immediately after sending request.');
// You can also handle errors:
child.on('error', (err) => {
console.error('Child process error:', err);
});Для запуска: Сохраните файлы как
fibonacci.js
и
parent.js
в том же каталоге, затем запустите
node parent.js
. Перед результатом Фибоначчи вы увидите сообщение «Основной процесс продолжается немедленно...», демонстрируя неблокирующее поведение.
worker_threads
: The Specialized Team within the Office
worker_threads
creates new threads within the same Node.js process. While each worker thread has its own JavaScript execution environment (V8 context) and event loop, they share a portion of the same underlying memory space with the main thread.
Ключевой вывод из интервью: сравните и противопоставьте child_process.fork() и worker_threads для разгрузки ресурсоемких задач в Node.js. Когда мы