Jak NodeJS może być „nieblokujący”?

14

Uczę się NodeJS i chciałem tylko coś wyjaśnić. W kilku wprowadzających podręcznikach i książkach do tej pory bardzo wcześnie opisali „nieblokującą” architekturę Node - a raczej, że możliwe jest (i zalecił cały punkt) kodowanie w sposób nieblokujący.

Na przykład ten przykład został podany w książce Czytam o asynchronicznym sposobie pobierania danych z bazy danych.

http.createServer(function (req, res) {
  database.getInformation(function (data) {
      res.writeHead(200);
      res.end(data);
  });
});

To, co się dzieje (jak rozumiem), to Węzeł wykonuje wywołanie do bazy danych, a następnie kontynuuje przetwarzanie wszystkiego, co może być następne na stosie wywołań. Po zakończeniu żądania bazy danych zmienna danych w anonimowej funkcji wywołania zwrotnego zostanie zapełniona, a funkcja ta dodana do stosu wywołań (a następnie wykonana, gdy dotrze do niego Węzeł).

Moje pytanie brzmi: co dokładnie przetwarza żądanie bazy danych? Z pewnością Node musi blokować? Co zajmuje się żądaniem bazy danych? Lub jeśli Węzeł czeka na asynchroniczne żądanie HTTP GET do zasobu zewnętrznego, co się dzieje z tym żądaniem, które umożliwia Węzłu kontynuowanie przetwarzania stosu wywołań i „blokowanie”?

Anonimowy
źródło

Odpowiedzi:

17

Gdy Node.js jest opisany jako „nieblokujący”, oznacza to w szczególności, że jego IO nie blokuje. Węzeł używa libuv do obsługi IO w sposób niezależny od platformy. W Windows używa portów zakończenia IO, w Uniksie używa epoll / kqueue / select / etc. Tak więc tworzy nie blokujące żądanie We / Wy (które może monitorować wątek w tle, ale nigdy nie jest narażone na JavaScript), a po wyniku umieszcza je w kolejce w pętli zdarzeń, która wywołuje wywołanie zwrotne JavaScript na głównej (czytaj: tylko) wątek JavaScript.

W przypadku baz danych zależy to od sposobu pisania biblioteki. Jeśli używa protokołu HTTP do komunikacji (jak niektóre bazy danych NoSQL), można go łatwo napisać w czystym JavaScript za pomocą standardowej httpbiblioteki węzłów . Jeśli zrobi to w inny sposób, to zależy od biblioteki. Można go napisać w C / C ++ i używać wątków w tle, o ile abstrakcja ta nigdy nie jest narażona na JavaScript.

Jeśli chodzi o pytanie o „przetwarzanie” żądania bazy danych, najlepiej wszystko, co należy zrobić, to wysłać prostą wiadomość do biblioteki (np. Instrukcję SQL lub inną kwerendę lub prośbę o połączenie), aw tym momencie swój JavaScript ciągle się śpiewa. Gdy biblioteka jest gotowa do wysłania wiadomości z powrotem, wysyła wiadomość z powrotem do kolejki zdarzeń węzła, która uruchamia wywołanie zwrotne, umożliwiając uruchomienie tego fragmentu kodu.

ckknight
źródło
Jest netpakiet, gdy http nie jest dostępny.
Florian Margaine,
Szczegóły, które mogą pomóc. Węzeł wykorzystuje silnik V8 JS. Jedną z najlepszych cech V8 jest łatwość wiązania procesów C / C ++ z wywołaniami JS. Funkcje JavaScript są blokowane, ale jedyne, co robi, to wywołać coś pod maską, co nie blokuje. Następnie inna funkcja JS odpowiada po zakończeniu tego procesu. Funkcje JS blokujące się nawzajem oznaczają, że nigdy nie będziesz mieć dwóch rzeczy próbujących zrobić coś takiego jak zaplanowanie zapisu w tym samym miejscu pliku w tym samym czasie, co, jak zakładam, wymaga zarządzania wieloma wątkami. Zawsze jest jasne, które żądanie było pierwsze w celu umieszczenia w kolejce.
Erik Reppen