← Назад к вопросам
Что такое back pressure для стримов и какая проблема была бы без него?
1.8 Middle🔥 302 комментариев
#Node.js и JavaScript#Кэширование и производительность
Комментарии (2)
🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое back pressure для стримов и какая проблема была бы без него?
Back pressure (обратное давление) — это механизм в Node.js Streams для управления скоростью передачи данных, когда потребитель данных (Writable Stream) обрабатывает медленнее, чем источник (Readable Stream) отправляет. Это предотвращает переполнение памяти.
Проблема без Back Pressure
// ПЛОХО — без управления скоростью
const fs = require('fs');
const readStream = fs.createReadStream('./huge-file.txt');
const writeStream = fs.createWriteStream('./output.txt');
readStream.on('data', (chunk) => {
writeStream.write(chunk);
});
// Что происходит:
// 1. Читаем chunk 1 (100KB) → буфер: 100KB
// 2. Читаем chunk 2 (100KB) → буфер: 200KB
// 3. Читаем chunk 3 (100KB) → буфер: 300KB
// ...
// 100. Читаем chunk 100 (100KB) → буфер: 10GB (!!! — ПРОБЛЕМА)
Как работает Back Pressure
const fs = require('fs');
const readStream = fs.createReadStream('./huge-file.txt');
const writeStream = fs.createWriteStream('./output.txt');
// ХОРОШО — управление back pressure
readStream.on('data', (chunk) => {
const canContinue = writeStream.write(chunk);
if (!canContinue) {
console.log('Back pressure: пауза');
readStream.pause(); // ПАУЗИРУЕМ ЧТЕНИЕ
}
});
// Когда буфер writeStream опустеет, возобнови чтение
writeStream.on('drain', () => {
console.log('Back pressure: продолжение');
readStream.resume(); // ВОЗОБНОВИ ЧТЕНИЕ
});
write() возвращаемые значения
const writeStream = fs.createWriteStream('./output.txt');
// write() возвращает boolean:
// true = буфер хороший, можно писать дальше
// false = буфер переполнен, нужна пауза!
const result = writeStream.write('Some data');
console.log(result); // true или false
if (result === false) {
console.log('Буфер переполнен, нужна пауза');
readStream.pause();
}
Пример с реальными числами
const fs = require('fs');
const readStream = fs.createReadStream('./huge-1gb-file.txt', {
highWaterMark: 64 * 1024 // 64KB chunks
});
const writeStream = fs.createWriteStream('./output.txt', {
highWaterMark: 16 * 1024 // 16KB буфер
});
// БЕЗ back pressure: буфер растёт до 1GB!
// С back pressure:
readStream.on('data', (chunk) => {
const canContinue = writeStream.write(chunk);
if (!canContinue) {
readStream.pause();
}
});
writeStream.on('drain', () => {
readStream.resume();
});
// Теперь буфер никогда не превышает 80KB
Pipe (автоматический back pressure)
// ЛУЧШИЙ способ — использовать pipe
// Pipe АВТОМАТИЧЕСКИ управляет back pressure
const fs = require('fs');
fs.createReadStream('./huge-file.txt')
.pipe(fs.createWriteStream('./output.txt'));
// Под капотом pipe делает ровно то же самое:
// if (!destination.write(chunk)) {
// source.pause();
// }
// destination.on('drain', () => {
// source.resume();
// });
highWaterMark (настройка буфера)
const fs = require('fs');
const readStream = fs.createReadStream('./file.txt', {
highWaterMark: 256 * 1024 // 256KB chunks
});
const writeStream = fs.createWriteStream('./output.txt', {
highWaterMark: 64 * 1024 // 64KB буфер
});
Проблемы без Back Pressure
- Out of Memory — весь файл загружается в память
- Потеря данных — переполненный буфер теряет данные
- Высокая задержка — большой буфер = большая задержка
- Нестабильность — непредсказуемое поведение
Правильный паттерн
const fs = require('fs');
const { pipeline } = require('stream');
function processFile(inputPath, outputPath) {
return new Promise((resolve, reject) => {
pipeline(
fs.createReadStream(inputPath),
fs.createWriteStream(outputPath),
(error) => {
if (error) reject(error);
else resolve();
}
);
});
}
await processFile('./huge-file.txt', './output.txt');
Back pressure — это критически важный механизм, без которого Node.js приложения с большими потоками данных быстро исчерпывают память и падают. Всегда используй pipe или явно управляй back pressure при работе со Streams.