libuv

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

libuv — это кроссплатформенная библиотека на C, обеспечивающая работу цикла событий Node.js, асинхронного I/O и пула потоков, составляя основу неблокирующей модели конкурентности JavaScript-среды выполнения Node.js. Когда приложение Node.js вызывает асинхронную операцию — например, чтение файла через fs.readFile(), DNS-запрос или установку TCP-соединения — libuv делегирует работу нативным асинхронным API операционной системы (epoll в Linux, kqueue в macOS, IOCP в Windows) или своему внутреннему пулу потоков из четырёх потоков по умолчанию для операций без нативной асинхронной поддержки. Цикл событий libuv проходит через отдельные фазы на каждой итерации: таймеры (setTimeout, setInterval), ожидающие колбэки, idle/prepare, poll (ожидание I/O), check (setImmediate) и close-колбэки — понимание этих фаз объясняет, почему колбэки process.nextTick() выполняются раньше любого I/O-события, и почему setImmediate() срабатывает после текущей фазы poll. Размер пула потоков libuv настраивается через переменную окружения UV_THREADPOOL_SIZE (по умолчанию 4, максимум 1024), что важно для серверов Node.js с интенсивным конкурентным использованием crypto, fs, dns.lookup() или нативных аддонов, делегирующих работу в пул. Профилирование насыщения пула потоков libuv — которое проявляется в виде задержки между отправкой I/O-операции и срабатыванием её колбэка — является важной техникой оптимизации производительности Node.js для высоконагруженных серверных сервисов.

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

libuv запускает JavaScript вне браузера через V8 + libuv. V8 компилирует JS в машинный код; libuv даёт event loop, async I/O очередь и thread pool для блокирующих операций (fs, dns, crypto). Runtime однопоточный по исполнению JS, но использует non-blocking I/O — мало ядер CPU обслуживают много конкурентных соединений. Современные релизы — LTS (чётные, 30 месяцев поддержки) и Current (нечётные, 6 месяцев).

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

Берите libuv для I/O-bound бэкендов (API, real-time, прокси), тулинга (build-шаги, CLI, codemods) и full-stack приложений с общими типами между сервером и клиентом. Пропустите для CPU-тяжёлой работы (обработка изображений, ML inference) без выноса в worker threads или нативные модули — однопоточный JS становится боттлнеком. В production всегда последний LTS.

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

Ловушки libuv: блокировка event loop синхронным кодом (один fs.readFileSync на горячем пути замораживает каждый запрос); console.log в production-горячих путях (медленнее, чем думают); закрепление на EOL Node-версии (security-дыры копятся); путаница CommonJS (require) и ESM (import) — у них тонкие различия в top-level await, расширениях файлов, динамической загрузке.

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

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

Проверить знания (1)

Загрузка вопросов…