Backpressure

Тема дорожной карты · Node.js

Backpressure (обратное давление) — это механизм, с помощью которого поток чтения сигнализирует своему источнику данных о необходимости замедлиться, когда потребитель не успевает обрабатывать данные, предотвращая неограниченный рост памяти в приложениях Node.js. В API потоков Node.js метод write() потока Writable возвращает false, когда его внутренний буфер заполнен, и источник данных должен приостановиться до тех пор, пока не возникнет событие drain — таков контракт backpressure, который делает потребление памяти предсказуемым. Игнорирование backpressure в серверных сервисах Node.js является распространённой причиной утечек памяти и аварийных остановок, особенно при передаче больших файлов, проксировании HTTP-ответов или потоковой передаче результатов из базы данных. Утилита stream.pipeline() и метод readable.pipe() автоматически обрабатывают распространение backpressure, что делает их более безопасными по сравнению с ручными вызовами read() и write(). Правильное управление backpressure необходимо для построения эффективных, надёжных потоковых конвейеров Node.js, обрабатывающих большие наборы данных без исчерпания памяти кучи.

Как это работает

Backpressure в Node — это unix-pipe-подобные абстракции для инкрементальных данных: Readable, Writable, Duplex, Transform. Используйте, когда данные большие (GB-файлы, сетевые загрузки) или бесконечные (логи, websockets). Современный Node поддерживает stream/promises и pipeline() для безопасной композиции с обработкой ошибок и cleanup. Web Streams API (ReadableStream, WritableStream) доступен с Node 18 — тот же shape, что в браузере.

Когда применять

Streams — когда payload может превысить RAM: загрузки файлов, большие выборки из БД, CSV-импорт. pipeline() (не сырой .pipe()) — чтобы ошибки пробрасывались, ресурсы закрывались. Для HTTP-ответов можно return res.pipe(stream) — forward без буферизации. Пропустите streams для маленьких in-memory данных — overhead API больше выгоды; берите buffer или string.

Типичные ошибки

Ловушки Backpressure: забытый backpressure (медленный consumer, быстрый producer = раздутая память); .pipe() без error-обработчиков (тихий провал); смешение object-mode и binary-mode streams; конверсия stream → Buffer ради JSON.parse (теряет смысл). for await (const chunk of stream) в современном Node — читается чище, чем event-обработчики.

Связанные понятия

Полезные ресурсы