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

Что такое 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

  1. Out of Memory — весь файл загружается в память
  2. Потеря данных — переполненный буфер теряет данные
  3. Высокая задержка — большой буфер = большая задержка
  4. Нестабильность — непредсказуемое поведение

Правильный паттерн

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.

Что такое back pressure для стримов и какая проблема была бы без него? | PrepBro