Jak Node.js obsługuje tysiące żądań

Mówi się, że Node.js jest jednowątkowy.

Mimo to obsługuje tysiące żądań, odczytuje pliki i wykonuje wywołania API bez zatrzymywania się.

Jak to działa?

Odpowiedzią jest libuv.

libuv to biblioteka w języku C. Nadaje ona Node.js możliwości asynchronicznego i nieblokującego wejścia/wyjścia (I/O). JavaScript nie potrafi samodzielnie odczytywać plików ani zarządzać gniazdami sieciowymi. Node.js wykorzystuje libuv, aby komunikować się z systemem operacyjnym.

Bez libuv JavaScript zatrzymałby się za każdym razem, gdy odczytywałbyś plik. Twoja aplikacja przestałaby odpowiadać.

Dzięki libuv odczyt pliku odbywa się w tle. JavaScript kontynuuje wykonywanie pozostałego kodu.

Przykład:

console.log("Start");

fs.readFile("data.txt", "utf8", (err, data) => {
  console.log(data);
});

console.log("End");

Wynik: Start End (zawartość pliku)

Node.js wypisuje "End" przed zakończeniem odczytu pliku. Nie czeka.

Jak libuv zarządza Twoim kodem:

• Pętla zdarzeń (Event Loop): libuv uruchamia pętlę, która sprawdza, czy zadania zostały zakończone. Gdy zadania dobiegają końca, libuv umieszcza funkcje zwrotne (callbacks) w kolejce. • Pula wątków (Thread Pool): JavaScript korzysta z jednego wątku. libuv korzysta z puli wątków roboczych. Domyślnie pula ta posiada 4 wątki. Wątki te obsługują ciężkie zadania, takie jak:

  • Operacje na systemie plików
  • Zapytania DNS
  • Kompresja
  • Kryptografia • Networking: libuv zarządza gniazdami HTTP, TCP i UDP. Pozwala to serwerom obsługiwać wiele połączeń jednocześnie. • Timery: libuv obsługuje setTimeout i setInterval.

Przepływ wykonania wygląda następująco:

  1. JavaScript uruchamia Twój kod.
  2. libuv przenosi ciężkie zadania do tła.
  3. JavaScript przechodzi do następnej linii.
  4. libuv powiadamia pętlę zdarzeń (Event Loop), gdy zadanie zostanie zakończone.
  5. Pętla zdarzeń uruchamia Twoją funkcję zwrotną (callback).

Wyobraź sobie pizzerię.

Bez libuv stoisz przy ladzie i co dziesięć sekund pytasz: „Czy moje jedzenie jest gotowe?”. Blokujesz kolejkę.

Dzięki libuv składasz zamówienie, siadasz i czekasz na powiadomienie. Możesz robić inne rzeczy, dopóki pizza nie będzie gotowa.

Podsumowanie:

• Wykonywanie JavaScript: V8 Engine • Pętla zdarzeń (Event Loop): libuv • Operacje wejścia/wyjścia plików (File I/O): libuv • Sieć: libuv • Timery: libuv

libuv to silnik, który sprawia, że Node.js jest szybki.

Źródło: https://dev.to/kavindotdev/understanding-libuv-the-engine-behind-nodejs-asynchronous-programming-3n7o