Skip to main content
Практика завдань

Що таке libuv і як він забезпечує асинхронний ввід/вивід у Node.js?

libuv: Асинхронний I/O двигун Node.js

libuv — це багатоплатформена бібліотека на C, яка забезпечує цикл подій, пул потоків та асинхронні I/O можливості, що підтримують Node.js. Без libuv неможливо було б реалізувати неблокуючу модель I/O в Node.js.


Огляд архітектури

┌──────────────────────────────────────────┐ │ Ваш код Node.js │ ├──────────────────────────────────────────┤ │ Ядро Node.js (JS API) │ │ http, fs, crypto, net, dns, child... │ ├──────────────────────────────────────────┤ │ Прив'язки Node.js (C++) │ ├──────────────────────────────────────────┤ │ libuv (C бібліотека) │ │ ┌─────────────┐ ┌────────────────────┐ │ │ │ Цикл подій │ │ Пул потоків │ │ │ │ (I/O poll) │ │ (за замовчуванням 4│ │ │ └─────────────┘ └────────────────────┘ │ ├──────────────────────────────────────────┤ │ Операційна система │ │ epoll (Linux) kqueue (macOS) IOCP │ └──────────────────────────────────────────┘

Що надає libuv

1. Цикл подій

Цикл подій опитує події I/O та виконує зворотні виклики, коли операції завершуються. Він абстрагує специфічні для ОС асинхронні механізми:

  • Linux: epoll
  • macOS / BSD: kqueue
  • Windows: IOCP (Порти завершення I/O)

2. Пул потоків

Деякі операції не можуть бути асинхронними на рівні ОС (файлова система на деяких платформах, DNS запити, криптографія). libuv надає пул потоків (за замовчуванням: 4 потоки) для обробки цих операцій:

js
// Ці операції використовують пул потоків libuv: fs.readFile() // файловий I/O crypto.pbkdf2() // ресурсоємна криптографія dns.lookup() // DNS розв'язування zlib compression // стиснення
js
// Мережева I/O (TCP, UDP) НЕ використовує пул потоків // Вона використовує асинхронні механізми ОС безпосередньо (epoll/kqueue) http.get() // без пулу потоків! net.connect() // без пулу потоків!

Розмір пулу потоків

bash
# За замовчуванням 4 потоки, можна збільшити: UV_THREADPOOL_SIZE=16 node server.js
js
// Або під час виконання (повинно бути встановлено перед будь-якою асинхронною роботою): process.env.UV_THREADPOOL_SIZE = '16';

Збільшуйте його, коли у вас багато одночасних:

  • Операцій з файловою системою
  • Викликів crypto.pbkdf2() / crypto.scrypt()
  • DNS запитів

Як працює асинхронна операція

1. JS викликає fs.readFile() 2. Прив'язка Node передає запит до libuv 3. libuv подає запит до пулу потоків (файл) або ОС (мережа) 4. Основний потік продовжує (цикл подій працює) 5. Пул потоків / ОС завершує роботу 6. libuv ставить зворотний виклик у чергу 7. Цикл подій підбирає зворотний виклик → виконує в JS

Практичний вплив: Виснаження пулу потоків

js
// Якщо UV_THREADPOOL_SIZE=4 і ви робите: for (let i = 0; i < 100; i++) { crypto.pbkdf2(password, salt, 10000, 512, 'sha512', callback); } // Тільки 4 виконуються паралельно! Інші ставляться в чергу. // Рішення: збільшити UV_THREADPOOL_SIZE

libuv Хендли та Запити

libuv використовує дві абстракції:

  • Хендли — довгоживучі об'єкти (TCP сервери, таймери, спостерігачі за файлами)
  • Запити — короткочасні операції (запит на запис, DNS запит)
js
const server = net.createServer(); // Хендл (довгоживучий) server.listen(3000); fs.readFile('./file', cb); // Запит (однократний)

Резюме

libuv є C двигуном за Node.js. Він реалізує:

  • Цикл подій з нативним асинхронним опитуванням I/O ОС
  • Пул потоків для блокуючих операцій
  • Хендли та запити для управління асинхронною роботою

Розуміння libuv допомагає зрозуміти чому Node.js швидкий для I/O, чому є обмеження пулу потоків, і як насправді працює цикл подій.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.

Дочитали статтю?
Практика завдань