Основная философия Node.js - "не блокировать цикл событий" (Don't Block the Event Loop). Вот ключевые подходы для обеспечения этого:
Node.js использует однопоточную модель с циклом событий. Долгие синхронные операции блокируют весь процесс.
// ПЛОХО: синхронная операция блокирует цикл событий
app.get('/blocking', (req, res) => {
const result = heavySyncComputation(); // Блокирует все!
res.send(result);
});
Все I/O операции в Node.js по умолчанию асинхронны:
// ХОРОШО: асинхронная операция не блокирует
app.get('/non-blocking', async (req, res) => {
const result = await heavyAsyncComputation(); // Не блокирует
res.send(result);
});
Для CPU-интенсивных задач используйте:
const { Worker } = require('worker_threads');
app.get('/compute', (req, res) => {
const worker = new Worker('./heavy-computation.js');
worker.on('message', (result) => {
res.send(result);
});
});
const { fork } = require('child_process');
app.get('/fork', (req, res) => {
const compute = fork('./compute.js');
compute.send('start');
compute.on('message', (result) => {
res.send(result);
});
});
Устанавливайте таймауты для операций:
app.get('/with-timeout', (req, res) => {
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('Timeout')), 5000);
});
Promise.race([longOperation(), timeoutPromise])
.then(result => res.send(result))
.catch(err => res.status(500).send(err.message));
});
Используйте все ядра CPU:
const cluster = require('cluster');
const os = require('os');
if (cluster.isMaster) {
os.cpus().forEach(() => cluster.fork());
} else {
// Worker process
require('./server');
}
fs.readFileSync
)// Потоковая обработка файла
const fs = require('fs');
app.get('/stream', (req, res) => {
const stream = fs.createReadStream('./large-file.txt');
stream.pipe(res); // Не блокирует цикл событий
});
Для действительно тяжелых задач используйте очереди (RabbitMQ, Bull):
const Queue = require('bull');
const queue = new Queue('heavyTasks');
app.post('/task', (req, res) => {
queue.add(req.body); // Обработается в фоне
res.send('Task queued');
});
Чтобы не блокировать обработку запросов других пользователей, используйте асинхронные операции, выносите тяжелые вычисления в отдельные потоки/процессы, применяйте кластеризацию и очереди. Главное правило - никогда не блокируйте цикл событий синхронными операциями.