Чи справді Node.js однотредовий?

pic

Чи справді Node.js є однотредовим?

Node.js часто хвалять за його інноваційну однотредову архітектуру, яка забезпечує високу продуктивність додатків. Але чи може така універсальна система справді працювати лише з одним потоком? Відповідь може здивувати вас.

Розуміння процесів і потоків ⚙️

Перед тим, як заглибитися в Node.js, давайте розрізнимо поняття процесів і потоків.

Що таке процес?

Процес — це екземпляр програми, що виконується на комп'ютері. Він включає:

  • Код виконання: Інструкції програми.
  • Сегмент даних: Глобальні та статичні змінні.
  • Куча: Динамічно виділена пам'ять.
  • Стек: Локальні змінні та виклики функцій.
  • Реєстри: Специфічне для процесора сховище, як-от лічильник програми.

Кожен процес працює незалежно і має свою власну область пам'яті.

Що таке потік?

Потік — це легкий виконавчий елемент всередині процесу. Потоки спільно використовують один і той самий код і сегменти даних, але мають незалежні стеки та реєстри. Це спільне середовище робить потоки ефективними для паралелізму, але водночас вони схильні до проблем з конкурентністю.

Чи є JavaScript однотредовим? ⚠️

Модель потоків JavaScript залежить від його середовища виконання:

  • У браузерах: JavaScript працює в однотредовому середовищі з циклом подій (Event Loop).
  • У Node.js: Він використовує однотредовий цикл подій разом з допоміжними потоками для деяких операцій.

Отже, JavaScript як мова не є однозначно однотредовим чи багатопотоковим; середовище визначає його поведінку.

Проблеми вводу/виводу (I/O) 🧮

Ефективне оброблення вводу/виводу є критично важливим для систем з високою продуктивністю. Ось чому I/O є вузьким місцем:

Обмеження апаратного забезпечення

  • Час доступу: Читання з пам'яті значно швидше, ніж з диска або мережі.
  • Пропускна здатність: Швидкість передачі даних в ОЗП набагато перевищує швидкість дискових або мережевих операцій.

Блокуюча поведінка

Традиційні операції вводу/виводу блокують потік до завершення, марнуючи цикли процесора.

Людський фактор

Застосунки часто залежать від вводу користувача, що призводить до непередбачуваних затримок.

Чи можуть потоки вирішити проблему? 🤔

Виглядає, що призначення окремого потоку для кожного запиту клієнта є вирішенням. Однак цей підхід має суттєві недоліки:

  1. Навантаження на ресурси: Потоки споживають пам'ять і ресурси процесора. Надмірна кількість потоків може погіршити продуктивність.
  2. Час простою: Потоки, які чекають на I/O, залишаються в простої, марнуючи ресурси.
  3. Складність: Керування потоками впроваджує такі ризики, як умови гонки (race conditions) і взаємні блокування (deadlocks).

Розумне рішення Node.js: Демультиплексування подій

Node.js використовує демультиплексування подій для ефективної обробки вводу/виводу без залежності від численних потоків.

Як це працює

Завдяки демультиплексуванню подій Node.js може:

  1. Реєструвати завдання вводу/виводу асинхронно.
  2. Використовувати один потік для керування кількома операціями.
  3. Обробляти завдання лише тоді, коли дані готові.

Операційні системи надають механізми, такі як epoll (Linux), kqueue (macOS) та IOCP (Windows) для демультиплексування подій.

Libuv: Спина Node.js 🏆

Node.js покладається на libuv, бібліотеку на C, яка забезпечує кросплатформенний асинхронний ввід/вивід.

Ключові компоненти Libuv

1. Черга подій

Структура, що зберігає події, що чекають обробки.

2. Цикл подій

Механізм, який безперервно:

  • Перевіряє чергу подій.
  • Розсилає події до їх обробників.

Робочий процес I/O в Node.js

  1. Реєстрація завдання: Libuv реєструє операції вводу/виводу в демультиплексор подій.
  2. Не блокуюче виконання: Операція виконується без блокування потоку.
  3. Повідомлення: Демультиплексор подій сигналізує, коли операція завершується.
    4.
    Обробка циклу подій (Event Loop): Результат обробляється циклом подій (Event Loop).

Правда про потоки в Node.js

Незважаючи на однотредову архітектуру циклу подій, Node.js використовує потоки за лаштунками для виконання певних завдань.

Пул потоків

Libuv включає пул потоків (за замовчуванням: 4 потоки) для обробки завдань, таких як:

  • Файловий ввід/вивід (I/O): Обмеження платформи не дозволяють виконувати справжній асинхронний файловий ввід/вивід.
  • Виконання ресурсоємних операцій: Шифрування, стиснення тощо.
  • Блокуючі операції DNS: Деякі DNS запити блокують потік.

Як працює пул потоків

  1. Завдання додаються до Черги завдань (Task Queue).
  2. Потік з пулу виконує завдання.
  3. Результати надсилаються в Чергу подій (Event Queue) для циклу подій (Event Loop).

Розмір пулу потоків можна налаштувати за допомогою:

UV_THREADPOOL_SIZE=8 node my_script.js

Магія Node.js ✨

Архітектура Node.js — однотредовий цикл подій, доповнений пулом потоків — поєднує ефективність і масштабованість. Такий гібридний підхід забезпечує високу продуктивність як для операцій з вводу/виводу (I/O), так і для ресурсоємних обчислень.

Висновок 🎉

Node.js не є повністю однотредовим. Хоча цикл подій працює в одному потоці, пул потоків libuv керує блокуючими завданнями за лаштунками. Це поєднання асинхронного програмування та потоків робить Node.js потужним інструментом для сучасної веб-розробки.

Розуміння цієї архітектури є ключем до повного використання потенціалу Node.js. Тому наступного разу, коли хтось скаже, що Node.js — це чисто однотредовий, поділіться глибшою правдою!

Вам також може сподобатись:

1) Як оптимізувати продуктивність вебсайту?

2) Тестування навантаження за допомогою Artillery: підготуйте ваше Node.js додаток до пікових навантажень

3) Топ-10 запитань на співбесідах зі розробки програмного забезпечення та як на них відповісти

4) Запитання на співбесіді для старшого рівня JavaScript Promise

5) Що таке індексація бази даних і чому це важливо?

6) Чи може ШІ змінити ландшафт торгівлі?

7) Яка мета пайплайна розгортання?

8) Аутентифікація на основі токенів: вибір між JWT та Paseto для сучасних додатків

9) Обмеження запитів API та стратегії запобігання зловживанням у Node.js для API з великим трафіком

Читати більше блогів можна тут

Поділіться своїм досвідом у коментарях, і давайте обговоримо, як вирішувати ці проблеми!

Слідкуйте за мною в Linkedin

Перекладено з: Is Node.js Truly Single-Threaded?

Leave a Reply

Your email address will not be published. Required fields are marked *