Що таке backpressure?
Термін Backpressure - один із ключових принципів потоків (streams) у Node.js. Він пояснює, як система запобігає перевантаженню, коли один потік виробляє дані швидше, ніж інший встигає їх обробляти.
Простими словами
Backpressure (зворотний тиск) - це механізм уповільнення передачі даних у ланцюжку потоків, щоб Writable Stream не "потонув" у даних, якщо Readable Stream надто швидкий.
Уяви шланг із водою: якщо вихід засмічений, тиск зростає - вода тече повільніше. У потоках Node.js усе аналогічно.
Чому це важливо
Без механізму backpressure:
Writable Streamпереповнив би свій внутрішній буфер,- пам'ять процесу (RAM) почала б зростати неконтрольовано,
- Event Loop завис би від навантаження.
Node.js вирішує це автоматично, якщо ти використовуєш .pipe() чи pipeline().
Як це працює
Кожен потік має внутрішній буфер - область пам'яті, куди тимчасово складаються chunk-и.
Writable.write(chunk)повертаєtrue, якщо буфер ще не переповнений.- Повертає
false, якщо потрібно призупинити читання, поки буфер не звільниться.
Коли буфер знову готовий - потік викидає подію drain, сигналізуючи, що можна продовжувати писати.
Приклад (без pipe)
const fs = require('fs');
const readable = fs.createReadStream('bigfile.txt');
const writable = fs.createWriteStream('copy.txt');
readable.on('data', (chunk) => {
const canContinue = writable.write(chunk);
if (!canContinue) {
// Буфер переповнений - призупиняємо читання
readable.pause();
}
});
writable.on('drain', () => {
// Буфер звільнився - відновлюємо читання
readable.resume();
});
readable.on('end', () => writable.end());Тут:
.write()повертаєfalse, колиWritableне встигає;.pause()і.resume()керують швидкістю читання вручну;.drainповідомляє, коли можна продовжити.
Приклад із pipe (автоматично)
Якщо ти використовуєш .pipe(), то backpressure керується автоматично:
const fs = require('fs');
fs.createReadStream('bigfile.txt')
.pipe(fs.createWriteStream('copy.txt'));.pipe()відстежує, коли Writable перевантажений,- призупиняє Readable за потреби,
- відновлює, коли Writable знову готовий писати.
Як це виглядає логічно
Readable → Writable
Якщо Writable.write() → false
↓
Readable.pause() ← потік зупинено
Коли Writable 'drain'
↓
Readable.resume() ← читання відновлюєтьсяПриклад через Transform Stream
Механізм працює й у ланцюжку з кількох потоків:
const { Transform, pipeline } = require('stream');
const fs = require('fs');
const slowTransform = new Transform({
transform(chunk, _, callback) {
setTimeout(() => {
this.push(chunk);
callback();
}, 100); // штучно уповільнюємо обробку
},
});
pipeline(
fs.createReadStream('input.txt'),
slowTransform,
fs.createWriteStream('output.txt'),
(err) => {
if (err) console.error('Помилка:', err);
else console.log('Обробку завершено');
}
);Навіть якщо трансформатор обробляє повільно, Node.js автоматично регулює потік - читання не виконуватиметься швидше, ніж запис.
Основна ідея в одній фразі
Backpressure - це "розумне гальмо", яке запобігає переповненню буфера, забезпечуючи баланс між швидкістю читання й запису.
Коротке порівняння
| Поведінка | Без backpressure | З backpressure |
|---|---|---|
| Потоки читають без зупинки | так | ні |
| Пам'ять зростає неконтрольовано | так | ні |
| Дані втрачаються чи обриваються | можливо | ні |
| Продуктивність стабільна | ні | так |
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.