Co to jest Node.js? [Zamknięte]

506

I nie do końca to, czego node.js chodzi. Może dlatego, że jestem głównie programistą aplikacji biznesowych. Co to jest i do czego służy?

Jak dotąd rozumiem, że:

  1. Model programowania jest sterowany zdarzeniami, zwłaszcza sposób, w jaki obsługuje I / O .
  2. Używa JavaScript, a parser to V8 .
  3. Można go łatwo wykorzystać do tworzenia współbieżnych aplikacji serwerowych.

Czy moje ustalenia są prawidłowe? Jeśli tak, to jakie są zalety zdarzeń we / wy, czy to coś więcej w przypadku współbieżności? Ponadto, czy Node.js ma stać się ramowym modelem programowania opartym na JavaScript (V8)?

Jeff
źródło

Odpowiedzi:

213

Myślę, że zaletami są:

  1. Tworzenie stron internetowych w dynamicznym języku (JavaScript) na maszynie wirtualnej, która jest niezwykle szybka (V8). Jest znacznie szybszy niż Ruby, Python lub Perl.

  2. Możliwość obsługi tysięcy jednoczesnych połączeń przy minimalnym nakładzie pracy w jednym procesie.

  3. JavaScript jest idealny dla pętli zdarzeń z pierwszorzędnymi obiektami funkcji i zamknięciami. Ludzie już wiedzą, jak z niego korzystać, wykorzystując go w przeglądarce do reagowania na zdarzenia inicjowane przez użytkownika.

  4. Wiele osób zna już JavaScript, nawet ludzie, którzy nie twierdzą, że są programistami. Jest to prawdopodobnie najpopularniejszy język programowania.

  5. Używanie JavaScript na serwerze WWW oraz w przeglądarce zmniejsza niedopasowanie impedancji między dwoma środowiskami programowania, które mogą komunikować struktury danych za pośrednictwem JSON, które działają tak samo po obu stronach równania. Duplikat kodu sprawdzania poprawności formularza może być współdzielony między serwerem a klientem itp.

postfuturist
źródło
1
@postfuturist: W rzeczywistości działa dobrze w porównaniu z wieloma alternatywami. W wielu przypadkach bardzo dobrze radzi sobie również z Javą 6. Schludny!
Adam Crossland,
1
@postfuturist Myślę, że porównałeś z java 6-Xint. Spróbuj porównać z java 6
server
@ iJK yammer.com to działająca aplikacja node.js
Gerard Banasig
1
Zabawne, pisałem JScript w ASP 10 lat temu, abym mógł (a) uniknąć okropności VBScript, (b) używać tego samego języka na kliencie i serwerze oraz (c) ponownie wykorzystywać własne i JS biblioteki do obsługi ciągów ... itd.
Antony Quinn
4
@Dlaczego edytowałeś ten post tylko dla „Legacy bzdury”? Nie sądzę, aby 212 osób zagłosowało na ten post, gdybyś napisał to od samego początku.
Julien Fouilhé
619

Używam Node.js w pracy i uważam, że jest bardzo wydajny. Zmuszony do wybrania jednego słowa do opisania Node.js, powiedziałbym „interesujący” (co nie jest czysto pozytywnym przymiotnikiem). Społeczność tętni życiem i rośnie. JavaScript, pomimo jego dziwactw, może być świetnym językiem do kodowania. Codziennie będziesz przemyślał własne rozumienie „najlepszych praktyk” i wzorców dobrze ustrukturyzowanego kodu. Node.js napływa teraz ogromna energia pomysłów, a praca w nim naraża cię na całe to myślenie - wielkie mentalne podnoszenie ciężarów.

Produkcja Node.js jest zdecydowanie możliwa, ale daleko od wdrożenia „pod klucz”, które wydaje się obiecane w dokumentacji. W Node.js v0.6.x „klaster” został zintegrowany z platformą, zapewniając jeden z podstawowych elementów składowych, ale mój skrypt „production.js” ma nadal ~ 150 linii logiki do obsługi takich rzeczy, jak tworzenie dziennika katalog, recykling martwych pracowników itp. Aby „poważna” usługa produkcyjna musiała być również przygotowana do ograniczania połączeń przychodzących i robienia wszystkiego, co Apache robi dla PHP . Szczerze mówiąc, Ruby on Rails ma dokładnie ten problem. Rozwiązuje się to za pomocą dwóch uzupełniających się mechanizmów: 1) Umieszczenie Ruby na szynach / węźle.Apache / Lighttd ). Serwer WWW może skutecznie obsługiwać zawartość statyczną, rejestrować dostęp, przepisywać adresy URL, przerywać SSL , egzekwować reguły dostępu i zarządzać wieloma pod-usługami. W przypadku żądań, które trafiły do ​​faktycznej usługi węzła, serwer proxy przekazuje żądanie przez. 2) Używając frameworka takiego jak Unicorn, który będzie zarządzał procesami roboczymi, okresowo je przetwarzał itd. Jeszcze nie znalazłem frameworka obsługującego Node.js, który wydaje się być całkowicie upieczony; może istnieć, ale jeszcze go nie znalazłem i nadal używam ~ 150 wierszy w ręcznie zwiniętym pliku „production.js”.

Czytanie frameworków, takich jak Express , wydaje się, że standardową praktyką jest po prostu obsługiwanie wszystkiego za pośrednictwem jednej usługi Node.js typu jack-of-all-trade ... „app.use (express.static (__ dirname + '/ public'))” . W przypadku usług i rozwoju o niskim obciążeniu prawdopodobnie nie jest to w porządku. Ale gdy tylko spróbujesz obciążyć swoją usługę dużym nakładem czasu i uruchamiać ją 24 godziny na dobę, 7 dni w tygodniu, szybko odkryjesz motywacje, które popychają duże witryny do posiadania dobrze upieczonego, utwardzonego kodu C, takiego jak Nginx, umieszczającego swoją stronę i obsługującego wszystkie żądań zawartości statycznej (... dopóki nie skonfigurujesz sieci CDN , takiej jak Amazon CloudFront )). Dla nieco humorystycznego i bezwstydnie negatywnego podejścia do tego zobacz tego faceta .

Node.js znajduje również coraz więcej zastosowań innych niż usługi. Nawet jeśli używasz czegoś innego do udostępniania treści internetowych, możesz nadal używać Node.js jako narzędzia do kompilacji, używając modułów npm do organizowania kodu, Browserify, aby połączyć go w pojedynczy zasób i uglify-js, aby zminimalizować go do wdrożenia . JavaScript do komunikacji z Internetem jest idealnym dopasowaniem impedancji i często czyni go najłatwiejszą drogą ataku. Na przykład, jeśli chcesz przeszukiwać wiele ładunków odpowiedzi JSON , powinieneś użyć mojego modułu podkreślenia CLI , paska narzędzi danych strukturalnych.

Za I przeciw:

  • Pro: Dla serwera, pisanie JavaScript na backendie było „lekiem na bramę” do nauki nowoczesnych wzorców interfejsu użytkownika. Nie boję się już pisania kodu klienta.
  • Pro: Zwykle zachęca do prawidłowego sprawdzania błędów (błąd jest zwracany przez praktycznie wszystkie wywołania zwrotne, co utrudnia programistom obsługę; także async.js i inne biblioteki obsługują paradygmat „błąd, jeśli którakolwiek z tych podzadań nie powiedzie się” znacznie lepiej niż typowy kod synchroniczny )
  • Pro: Niektóre interesujące i zwykle trudne zadania stają się trywialne - takie jak uzyskanie statusu zadań w locie, komunikacja między pracownikami lub współdzielenie stanu pamięci podręcznej
  • Pro: Ogromna społeczność i mnóstwo świetnych bibliotek opartych na solidnym menedżerze pakietów (npm)
  • Przeciw: JavaScript nie ma standardowej biblioteki. Tak się przyzwyczajasz do importowania funkcjonalności, że czujesz się dziwnie, gdy używasz JSON.parse lub innej metody wbudowanej, która nie wymaga dodawania modułu npm. Oznacza to, że istnieje pięć wersji wszystkiego. Nawet moduły zawarte w „rdzeniu” Node.js mają pięć dodatkowych wariantów, jeśli nie będziesz zadowolony z domyślnej implementacji. Prowadzi to do szybkiej ewolucji, ale także do pewnego stopnia zamieszania.

W porównaniu z prostym modelem jednoprocesowym na żądanie ( LAMP ):

  • Pro: Skalowalny do tysięcy aktywnych połączeń. Bardzo szybki i bardzo wydajny. W przypadku floty internetowej może to oznaczać 10-krotną redukcję wymaganej liczby pudeł w porównaniu z PHP lub Ruby
  • Pro: Pisanie równoległych wzorów jest łatwe. Wyobraź sobie, że musisz pobrać trzy (lub N) obiekty BLOB z Memcached . Czy to w PHP ... czy właśnie napisałeś kod, który pobiera pierwszą kroplę, potem drugą, a potem trzecią? Wow, to wolno. Istnieje specjalny moduł PECL do rozwiązania tego konkretnego problemu dla Memcached, ale co zrobić, jeśli chcesz pobrać niektóre Memcached dane równolegle z zapytaniem do bazy danych? W Node.js, ponieważ paradygmat jest asynchroniczny, zlecenie wykonania wielu czynności jednocześnie jest bardzo naturalne.
  • Przeciw: kod asynchroniczny jest zasadniczo bardziej złożony niż kod synchroniczny, a krzywa uczenia się z góry może być trudna dla programistów bez dokładnego zrozumienia, co w rzeczywistości oznacza równoczesne wykonywanie. Jest to jednak o wiele mniej trudne niż pisanie kodu wielowątkowego z blokowaniem.
  • Przeciw: Jeśli żądanie wymagające dużej mocy obliczeniowej działa na przykład przez 100 ms, zatrzyma przetwarzanie innych żądań, które są obsługiwane w tym samym procesie Node.js ... AKA, wielozadaniowość kooperacyjna . Można to złagodzić za pomocą wzorca Web Workers (wydzielenie podprocesu do wykonania kosztownego zadania). Alternatywnie, możesz użyć dużej liczby pracowników Node.js i pozwolić każdemu z nich obsługiwać tylko jedno żądanie jednocześnie (wciąż dość wydajne, ponieważ nie ma procesu recyklingu).
  • Przeciw: Uruchamianie systemu produkcyjnego jest DUŻO bardziej skomplikowane niż model CGI, taki jak Apache + PHP, Perl , Ruby itp. Nieobsługiwane wyjątki obniżą cały proces, wymagając logiki do zrestartowania nieudanych pracowników (patrz klaster ). Moduły z błędnym natywnym kodem mogą spowodować poważne awarie procesu. Za każdym razem, gdy umiera pracownik, wszelkie obsługiwane przez niego żądania są odrzucane, więc jeden błędny interfejs API może łatwo obniżyć jakość usług dla innych interfejsów API współhostowanych.

W przeciwieństwie do pisania „prawdziwej” usługi w Javie / C # / C (C? Naprawdę?)

  • Pro: Wykonanie asynchroniczne w Node.js jest łatwiejsze niż zabezpieczenie wątków gdzie indziej i zapewne zapewnia większą korzyść. Node.js jest zdecydowanie najmniej bolesnym paradygmatem asynchronicznym, w jakim kiedykolwiek pracowałem. Przy dobrych bibliotekach jest tylko nieco trudniejszy niż pisanie kodu synchronicznego.
  • Pro: Brak błędów wielowątkowości / blokowania. To prawda, że ​​inwestujesz z góry w pisanie bardziej pełnego kodu, który wyraża właściwy asynchroniczny przepływ pracy bez operacji blokowania. I musisz napisać kilka testów i sprawić, by coś zadziałało (jest to język skryptowy, a nazwy zmiennych grubych palców są wychwytywane tylko w czasie testu jednostkowego). ALE, kiedy już uruchomisz, obszar dla heisenbugów - dziwne problemy, które pojawiają się tylko raz na milion przebiegów - ten obszar jest po prostu znacznie mniejszy. Podatki, które piszą kod Node.js, są w dużym stopniu ładowane od początku do fazy kodowania. Potem masz tendencję do uzyskania stabilnego kodu.
  • Pro: JavaScript jest znacznie lżejszy do wyrażania funkcjonalności. Trudno to udowodnić słowami, ale JSON , dynamiczne pisanie, notacja lambda, prototypowe dziedziczenie, lekkie moduły, cokolwiek ... po prostu potrzeba mniej kodu, aby wyrazić te same pomysły.
  • Przeciw: Może naprawdę lubisz usługi kodowania w Javie?

Aby uzyskać inne spojrzenie na JavaScript i Node.js, sprawdź From Java to Node.js , post na blogu na temat wrażeń i doświadczeń programisty Java na temat uczenia się Node.js.


Moduły Rozważając węzeł, pamiętaj, że wybór bibliotek JavaScript DEFINICUJE twoje wrażenia. Większość ludzi używa co najmniej dwóch, pomocnika asynchronicznego wzorca (Step, Futures, Async) i modułu cukru JavaScript ( Underscore.js ).

Cukier pomocnika / JavaScript:

  • Underscore.js - użyj tego. Po prostu to zrób. Czyni twój kod ładnym i czytelnym dzięki takim rzeczom jak _.isString () i _.isArray (). Nie jestem do końca pewien, jak inaczej napisać bezpieczny kod. Ponadto, aby uzyskać ulepszone wiersze poleceń, sprawdź mój własny interfejs Underscore-CLI .

Moduły wzorców asynchronicznych:

  • Krok - bardzo elegancki sposób wyrażania kombinacji działań szeregowych i równoległych. Moje osobiste zalecenie. Zobacz mój post o tym, jak wygląda kod Step.
  • Kontrakty terminowe - o wiele bardziej elastyczny (czy to naprawdę dobra rzecz?) Sposób wyrażania zamówienia poprzez wymagania. Potrafi wyrazić takie rzeczy jak: „uruchom a, b, c równolegle. Kiedy A i B zakończą, zacznij AB. Kiedy A i C zakończą, zacznij AC”. Taka elastyczność wymaga większej uwagi, aby uniknąć błędów w przepływie pracy (np. Nigdy nie wywoływać oddzwaniania lub dzwonić wielokrotnie). Zobacz post Raynosa na temat korzystania z futures (jest to post, który sprawił, że „dostałem” futures).
  • Asynchronizacja - bardziej tradycyjna biblioteka z jedną metodą dla każdego wzorca. Zacząłem od tego przed moją religijną konwersją na krok i późniejszą świadomością, że wszystkie wzorce w Async można wyrazić na Kroku za pomocą jednego bardziej czytelnego paradygmatu.
  • TameJS - napisany przez OKCupid, to prekompilator, który dodaje nową funkcję podstawową języka „czekaj” na eleganckie pisanie szeregowych i równoległych przepływów pracy. Wzór wygląda niesamowicie, ale wymaga wstępnej kompilacji. Nadal zastanawiam się nad tym.
  • StreamlineJS - konkurent TameJS. Pochylam się w kierunku Tame, ale możesz podjąć decyzję.

Lub, aby przeczytać wszystko o bibliotekach asynchronicznych, zobacz ten wywiad panelowy z autorami.

Framework sieciowy:

  • Ekspresowe środowisko Ruby on Rails-esk do organizowania stron internetowych. Używa JADE jako silnika szablonów XML / HTML, co sprawia, że ​​budowanie HTML jest o wiele mniej bolesne, a nawet eleganckie.
  • jQuery Chociaż technicznie nie jest modułem węzła, jQuery szybko staje się de facto standardem dla interfejsu użytkownika po stronie klienta. jQuery zapewnia selektory podobne do CSS do „przeszukiwania” zestawów elementów DOM, na których można następnie operować (programy obsługi, właściwości, style itp.). W tym samym stylu, platforma Bootstrap CSS na Twitterze , Backbone.js dla wzoru MVC i Browserify.js, aby połączyć wszystkie pliki JavaScript w jeden plik. Wszystkie te moduły stają się de facto standardami, więc powinieneś je przynajmniej sprawdzić, jeśli o nich nie słyszałeś.

Testowanie:

  • JSHint - Musisz użyć; Na początku nie korzystałem z tego, co teraz wydaje się niezrozumiałe. JSLint dodaje kilka podstawowych weryfikacji uzyskanych za pomocą skompilowanego języka, takiego jak Java. Niedopasowany nawias, niezadeklarowane zmienne, literówki o wielu kształtach i rozmiarach. Możesz także włączyć różne formy tego, co nazywam „trybem analnym”, w którym weryfikujesz styl białych znaków i tak dalej, co jest OK, jeśli to twoja filiżanka herbaty - ale prawdziwa wartość pochodzi z natychmiastowego uzyskiwania informacji zwrotnych na temat dokładnego numeru wiersza, w którym zapomniałeś zamykającego „)” ... bez konieczności uruchamiania kodu i uderzania w linię obrażającą. „JSHint” jest bardziej konfigurowalny wariant Douglas Crockforda „s JSLint .
  • Konkurent Mocha do ślubowań, które zaczynam preferować. Oba frameworki radzą sobie z podstawami wystarczająco dobrze, ale złożone wzory są łatwiejsze do wyrażenia w Mokce.
  • Ślubowanie Ślubowanie jest naprawdę bardzo eleganckie. I drukuje piękny raport (--spec) pokazujący, które przypadki testowe przeszły / nie powiodły się. Poświęć 30 minut na naukę, a przy minimalnym wysiłku możesz stworzyć podstawowe testy modułów.
  • Zombie - Bezgłowe testowanie HTML i JavaScript za pomocą JSDom jako wirtualnej „przeglądarki”. Bardzo potężne rzeczy. Połącz go z Replay, aby uzyskać błyskawiczne, deterministyczne testy kodu w przeglądarce.
  • Komentarz na temat tego, jak „pomyśleć o” testowaniu:
    • Testowanie nie jest opcjonalne. W przypadku dynamicznego języka, takiego jak JavaScript, jest bardzo mało sprawdzeń statycznych. Na przykład przekazanie dwóch parametrów do metody, która oczekuje 4, nie ulegnie awarii, dopóki kod nie zostanie wykonany. Dość niski pasek do tworzenia błędów w JavaScript. Podstawowe testy są niezbędne do uzupełnienia luki weryfikacyjnej w skompilowanych językach.
    • Zapomnij o sprawdzeniu poprawności, po prostu uruchom kod. Dla każdej metody moim pierwszym przypadkiem sprawdzania poprawności jest „nic się nie psuje”, i to jest przypadek, który najczęściej się uruchamia. Udowodnienie, że Twój kod działa bez rzucania, wyłapuje 80% błędów i zrobi tak wiele, aby zwiększyć pewność kodu, że cofniesz się i dodasz niuansowe przypadki sprawdzania poprawności, które pominęłeś.
    • Zacznij od małego i przełam barierę bezwładności. Wszyscy jesteśmy leniwi i potrzebujemy czasu, a testowanie można łatwo uznać za „dodatkową pracę”. Więc zacznij od małej. Napisz przypadek testowy 0 - załaduj moduł i zgłoś sukces. Jeśli zmusisz się do zrobienia właśnie tyle, wtedy bariera bezwładności w testowaniu zostanie przełamana. To mniej niż 30 minut na zrobienie tego za pierwszym razem, łącznie z przeczytaniem dokumentacji. Teraz napisz przypadek testowy 1 - wywołaj jedną ze swoich metod i sprawdź, czy „nic się nie psuje”, to znaczy, że nie otrzymasz z powrotem błędu. Przypadek testowy 1 powinien zająć Ci mniej niż minutę. Po zniknięciu bezwładności łatwo jest stopniowo zwiększać zasięg testu.
    • Teraz rozwijaj swoje testy za pomocą kodu. Nie daj się zastraszyć, jak wyglądałby „prawidłowy” kompleksowy test z fałszywymi serwerami i tym podobne. Kod zaczyna się od prostej i ewoluuje, aby obsługiwać nowe przypadki; testy też powinny. Gdy dodajesz nowe przypadki i nową złożoność do swojego kodu, dodaj przypadki testowe, aby wykonać nowy kod. Gdy znajdziesz błędy, dodaj weryfikacje i / lub nowe przypadki, aby zakryć wadliwy kod. Kiedy debugujesz i tracisz zaufanie do fragmentu kodu, wróć i dodaj testy, aby udowodnić, że robi to, co myślisz. Przechwytuj ciągi przykładowych danych (z innych usług, do których dzwonisz, zeskrobywanych witryn, cokolwiek) i przesyłaj je do swojego kodu parsującego. Kilka przypadków tutaj, poprawione sprawdzanie poprawności, a skończysz z wysoce niezawodnym kodem.

Sprawdź także oficjalną listę zalecanych modułów Node.js. Jednak Wiki Node Modules GitHub jest znacznie bardziej kompletna i stanowi dobry zasób.


Aby zrozumieć Węzeł, warto rozważyć kilka kluczowych opcji projektowania:

Node.js jest OPARTY NA ZDARZENIACH i ASYNCHRONICZNY / NIE BLOKUJĄCY. Zdarzenia, takie jak przychodzące połączenie HTTP, uruchamiają funkcję JavaScript, która wykonuje trochę pracy i uruchamia inne asynchroniczne zadania, takie jak łączenie się z bazą danych lub pobieranie zawartości z innego serwera. Po uruchomieniu tych zadań funkcja zdarzenia kończy się, a Node.js wraca do trybu uśpienia. Gdy tylko wydarzy się coś innego, na przykład nawiązywane połączenie z bazą danych lub serwer zewnętrzny odpowiadający treścią, uruchamiane są funkcje wywołania zwrotnego i wykonuje się więcej kodu JavaScript, potencjalnie uruchamiając jeszcze więcej zadań asynchronicznych (takich jak zapytanie do bazy danych). W ten sposób Node.js z radością przeplata działania dla wielu równoległych przepływów pracy, uruchamiając wszelkie działania, które są odblokowane w dowolnym momencie. Dlatego Node.js wykonuje tak świetną robotę, zarządzając tysiącami jednoczesnych połączeń.

Dlaczego nie użyć jednego procesu / wątku na połączenie, jak wszyscy inni?W Node.js nowe połączenie jest tylko bardzo małą alokacją sterty. Przyspieszenie nowego procesu wymaga znacznie więcej pamięci, megabajt na niektórych platformach. Ale rzeczywisty koszt to narzut związany z przełączaniem kontekstu. Kiedy masz 10 ^ 6 wątków jądra, jądro musi wykonać wiele pracy, zastanawiając się, kto powinien wykonać następny. Sporo pracy poświęcono na zbudowanie harmonogramu O (1) dla Linuksa, ale ostatecznie o wiele bardziej efektywne jest posiadanie jednego procesu sterowanego zdarzeniem niż 10 ^ 6 procesów rywalizujących o czas procesora. Ponadto, w warunkach przeciążenia, model wieloprocesowy zachowuje się bardzo słabo, głodując krytyczne usługi administracji i zarządzania, szczególnie SSHD (co oznacza, że ​​nie możesz nawet zalogować się do skrzynki, aby dowiedzieć się, jak naprawdę jest przykręcony).

Node.js jest POJEDYNCZY GWINTOWANY i BEZPŁATNY . Node.js, jako bardzo przemyślany wybór projektu, ma tylko jeden wątek na proces. Z tego powodu dostęp do danych jednocześnie przez wiele wątków jest zasadniczo niemożliwy. Dlatego nie są potrzebne żadne blokady. Wątki są trudne. Naprawdę bardzo ciężko. Jeśli w to nie wierzysz, nie wykonałeś wystarczająco dużo programowania wątkowego. Prawidłowe zablokowanie jest trudne i powoduje błędy, które są naprawdę trudne do wyśledzenia. Wyeliminowanie blokad i wielowątkowości sprawia, że ​​jedna z najgorszych klas błędów po prostu odchodzi. To może być największa zaleta węzła.

Ale jak mogę skorzystać z mojego 16-rdzeniowego urządzenia?

Dwie drogi:

  1. W przypadku dużych zadań obliczeniowych, takich jak kodowanie obrazu, Node.js może odpalać procesy potomne lub wysyłać wiadomości do dodatkowych procesów roboczych. W tym projekcie miałbyś jeden wątek zarządzający przepływem zdarzeń i procesami N wykonującymi ciężkie zadania obliczeniowe i przełamującymi pozostałe 15 procesorów.
  2. Aby skalować przepustowość w usłudze sieciowej, powinieneś uruchomić wiele serwerów Node.js na jednym urządzeniu, po jednym na rdzeń, używając klastra (w Node.js v0.6.x, oficjalny moduł „klastra”, który jest tutaj powiązany, zastępuje wersję learnboost, która ma inny interfejs API). Te lokalne serwery Node.js mogą następnie konkurować w gnieździe o akceptację nowych połączeń, równoważąc obciążenie między nimi. Po zaakceptowaniu połączenia zostaje ono ściśle powiązane z jednym z tych współużytkowanych procesów. Teoretycznie brzmi to źle, ale w praktyce działa całkiem dobrze i pozwala uniknąć kłopotów z pisaniem bezpiecznego kodu. Oznacza to również, że Node.js uzyskuje doskonałe powinowactwo do pamięci podręcznej procesora, efektywniej wykorzystując przepustowość pamięci.

Node.js pozwala robić naprawdę potężne rzeczy bez zerwania. Załóżmy, że masz program Node.js, który wykonuje różne zadania, nasłuchujepoleceń na porcie TCP i koduje niektóre obrazy. Za pomocą pięciu wierszy kodu możesz dodać portal zarządzania oparty na HTTP, który pokazuje aktualny stan aktywnych zadań. ŁATWO jest zrobić:

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end(myJavascriptObject.getSomeStatusInfo());
}).listen(1337, "127.0.0.1");

Teraz możesz kliknąć adres URL i sprawdzić status swojego uruchomionego procesu. Dodaj kilka przycisków, a otrzymasz „portal zarządzania”. Jeśli masz działający skrypt Perl / Python / Ruby, samo „wrzucenie portalu zarządzania” nie jest do końca proste.

Ale czy JavaScript nie jest wolny / zły / zły / spawn-of-the-devil? JavaScript ma pewne dziwne dziwactwa, ale z „dobrymi stronami” jest tam bardzo mocny język, aw każdym razie JavaScript jest językiem na kliencie (przeglądarce). JavaScript zostanie tutaj; inne języki celują w to jako IL, a światowej klasy talent konkuruje o produkcję najbardziej zaawansowanych silników JavaScript. Ze względu na rolę JavaScriptu w przeglądarce włożono ogromny wysiłek inżynieryjny w szybkie przyspieszenie JavaScript. V8to najnowszy i największy silnik javascript, przynajmniej na ten miesiąc. Zdmuchuje inne języki skryptowe zarówno pod względem wydajności ORAZ stabilności (patrząc na ciebie, Ruby). I tylko poprawi się to dzięki ogromnym zespołom pracującym nad tym problemem w Microsoft, Google i Mozilli, konkurujących o zbudowanie najlepszego silnika JavaScript (To już nie jest „interpreter” JavaScript, ponieważ wszystkie nowoczesne silniki robią mnóstwo JITkompilacja pod maską z interpretacją tylko jako rezerwowy kod dla kodu jednorazowego wykonania). Tak, wszyscy chcielibyśmy naprawić kilka dziwniejszych wyborów językowych JavaScript, ale tak naprawdę nie jest tak źle. A język jest tak elastyczny, że tak naprawdę nie kodujesz JavaScript, kodujesz Step lub jQuery - bardziej niż jakikolwiek inny język, w JavaScript biblioteki definiują to doświadczenie. Aby budować aplikacje internetowe, i tak musisz znać JavaScript, więc kodowanie go na serwerze ma pewnego rodzaju synergię umiejętności. Sprawiło, że nie boję się pisać kodu klienta.

Poza tym, jeśli NAPRAWDĘ nienawidzisz JavaScript, możesz użyć cukru syntaktycznego, takiego jak CoffeeScript . Lub cokolwiek innego, co tworzy kod JavaScript, na przykład Google Web Toolkit (GWT).

Mówiąc o JavaScript, co to jest „zamknięcie”? - Właściwie fantazyjny sposób powiedzenia, że ​​zachowuje się zmienne o zasięgu leksykalnym w łańcuchach połączeń. ;) Lubię to:

var myData = "foo";
database.connect( 'user:pass', function myCallback( result ) {
    database.query("SELECT * from Foo where id = " + myData);
} );
// Note that doSomethingElse() executes _BEFORE_ "database.query" which is inside a callback
doSomethingElse();

Widzisz, jak możesz po prostu użyć „myData” bez robienia czegokolwiek niewygodnego, jak wbicie go do obiektu? I inaczej niż w Javie, zmienna „myData” nie musi być tylko do odczytu. Ta potężna funkcja języka sprawia, że ​​programowanie asynchroniczne jest znacznie mniej szczegółowe i mniej bolesne.

Pisanie kodu asynchronicznego zawsze będzie bardziej skomplikowane niż pisanie prostego skryptu jednowątkowego, ale w Node.js nie jest to dużo trudniejsze i zyskujesz wiele korzyści oprócz wydajności i skalowalności dla tysięcy jednoczesnych połączeń. ..

Dave Dopson
źródło
„zmienna„ myData ”nie musi być tylko do odczytu” - wygląda na to, że chciałbyś zachować ją przez cały czas na niezmienionym poziomie, aby uniknąć problemów z współbieżnością, prawda?
Nick
1
@Nick - to nieprawda. „problemy z współbieżnością” są łagodzone przez fakt, że węzeł jest jednowątkowy. Blokowanie w węźle po prostu nie istnieje; nie jest potrzebny w paradygmacie jednowątkowym.
Dave Dopson
Klaster został zintegrowany z rdzeniem węzła w węźle 0.6 stackoverflow.com/a/8470986/212702 nodejs.org/docs/latest/api/cluster.html#cluster_cluster
Laurent Debricon
1
ps, uwaga dodatkowa - faktycznie edytowałem go wystarczająco dużo razy, aby post stał się „społecznością wiki” (próg to 10 edycji). Pomyślałem, że to jakiś zaszczyt, gdy w rzeczywistości blokuje on wzrost reputacji dzięki pozytywnym opiniom. W końcu jeden z wyborców sprzed CW-u kliknął „nie głosuj” (mam nadzieję, że przez przypadek :) i straciłem reputację ... zdezorientowany napisałem meta.stackexchange.com/questions/129941/... i zostałem przeszkolony w „Społeczności” Wiki ”tak naprawdę znaczy. Mody były na tyle miłe, że usunęły status CW. :)
Dave Dopson
1
@John - mój komentarz do debugowania absolutnie dotyczy również waniliowego asnyc. Aby przerwać debugowanie, wystarczy zawinąć jakieś wywołanie funkcji w „process.nextTick (...)”. Następnie, gdy wyrzuci, mój ślad stosu rozpocznie się od process.nextTick; nie tak pomocne. To, co naprawdę chcę wiedzieć to: „Który stos zaplanował proces. Nazywam te dane „łańcuchami przyczynowymi” i przypomina mi to „wywoływane przez” w obsłudze wyjątków Javy ... rzuty kodu niskiego poziomu, kod średniego poziomu przechwytuje wyjątek LL i zgłasza FrameworkMethodFailedException - bez „wywoływanego przez” stosu z LL kod zostanie utracony.
Dave Dopson
85

V8 to implementacja JavaScript. Pozwala uruchamiać niezależne aplikacje JavaScript (między innymi).

Node.js jest po prostu biblioteką napisaną dla V8, która wykonuje zdarzenia I / O. Ta koncepcja jest nieco trudniejsza do wyjaśnienia i jestem pewien, że ktoś odpowie lepiej, niż ja ... Istotą jest to, że zamiast robić jakieś dane wejściowe lub wyjściowe i czekać, aż to się stanie, po prostu nie czekaj do końca. Na przykład zapytaj o czas ostatniej edycji pliku:

// Pseudo code
stat( 'somefile' )

Może to potrwać kilka milisekund lub może potrwać kilka sekund. Za pomocą zdarzeń I / O po prostu odpalasz żądanie i zamiast czekać, dołączasz oddzwanianie, które uruchamia się po zakończeniu żądania:

// Pseudo code
stat( 'somefile', function( result ) {
  // Use the result here
} );
// ...more code here

To sprawia, że ​​przypomina kod JavaScript w przeglądarce (na przykład z funkcjonalnością stylu Ajax ).

Aby uzyskać więcej informacji, zapoznaj się z artykułem Node.js jest naprawdę ekscytujący, co stanowiło moje wprowadzenie do biblioteki / platformy ... Uważam, że jest całkiem niezły.

rfunduk
źródło
4
W jaki sposób wdrażane jest zdarzenie we / wy bez użycia blokad, wątków, procesów, zamknięć? Mam wrażenie, że koncepcje są bardzo podobne do programowania funkcjonalnego i Erlanga.
Jeff
1
O ile mi wiadomo, jest zaimplementowany jako prosta pętla zdarzeń. Wersja 8 ma już funkcję wywołania zwrotnego / etc, podobnie jak każda implementacja javascript.
rfunduk
2
Pętla zdarzeń We / Wy w node.js oznacza, że ​​w danym momencie wykonywana jest co najwyżej jedna rzecz. Widzę dwa znaczące korzyści: Nie ma narzutu związanego z przełączaniem wątków, więc node.js jest bardzo szybki, a po drugie wiele typowych błędów współbieżności, z których Java jest znana, nie jest możliwych.
dokładnie
1
„W jaki sposób wdrażane jest zdarzenie we / wy bez użycia ... zamknięć?” JavaScript obsługuje zamknięcia i są one używane przez cały czas w node.js (anonimowe funkcje i przykład tutaj).
panzi
@panzi: Nie zauważył, że Jeffrey umieścił zamknięcia na swojej liście rzeczy, które node.js jest zaimplementowane „bez”. Oczywiście każda funkcja w javascript jest zamknięta wokół swojego zakresu :)
rfunduk
35

Node.js to narzędzie wiersza polecenia typu open source zbudowane dla kodu JavaScript po stronie serwera. Możesz pobrać tarball , skompilować i zainstalować źródło. Pozwala uruchamiać programy JavaScript.

JavaScript jest wykonywany przez V8 , silnik JavaScript opracowany przez Google, który jest używany w przeglądarce Chrome . Używa JavaScript API, aby uzyskać dostęp do sieci i systemu plików.

Jest popularny ze względu na swoją wydajność i zdolność do wykonywania operacji równoległych.

Zrozumienie node.js to najlepsze wytłumaczenie node.js , jakie do tej pory znalazłem.

Poniżej kilka dobrych artykułów na ten temat.

Asif Mushtaq
źródło
13

Zamknięcia są sposobem na wykonanie kodu w kontekście, w którym został utworzony.

Dla pewności oznacza to, że możesz zdefiniować zmienne, a następnie zainicjować nieblokującą funkcję We / Wy i wysłać jej anonimową funkcję dla jej wywołania zwrotnego.

Po zakończeniu zadania funkcja wywołania zwrotnego zostanie wykonana w kontekście zmiennych, jest to zakończenie.

Powodem, dla którego zamknięcia są tak dobre do pisania aplikacji z nieblokującymi wejściami / wyjściami, jest to, że bardzo łatwo jest zarządzać kontekstem funkcji wykonujących asynchronicznie.

Fire Crow
źródło
8

Dwa dobre przykłady dotyczą sposobu zarządzania szablonami i korzystania z progresywnych ulepszeń. Potrzebujesz tylko kilku lekkich fragmentów kodu JavaScript, aby działał idealnie.

Zdecydowanie zalecamy obejrzenie i przeczytanie tych artykułów:

Wybierz dowolny język i spróbuj zapamiętać, w jaki sposób zarządzasz szablonami plików HTML i co musiałeś zrobić, aby zaktualizować pojedynczą nazwę klasy CSS w strukturze DOM (na przykład użytkownik kliknął element menu i chcesz, aby był on oznaczony jako „wybrano” i zaktualizuj zawartość strony).

W Node.js jest to tak proste, jak w kodzie JavaScript po stronie klienta. Pobierz węzeł DOM i zastosuj do tego klasę CSS. Zdobądź swój węzeł DOM i innerHTML treść (aby to zrobić, potrzebujesz dodatkowego kodu JavaScript. Przeczytaj artykuł, aby dowiedzieć się więcej).

Innym dobrym przykładem jest to, że możesz dostosować swoją stronę internetową do włączonej lub wyłączonej obsługi JavaScript za pomocą tego samego fragmentu kodu. Wyobraź sobie, że masz wybraną datę w JavaScript, która pozwoliłaby twoim użytkownikom wybrać dowolną datę za pomocą kalendarza. Możesz napisać (lub użyć) ten sam fragment kodu JavaScript, aby włączyć lub wyłączyć JavaScript.

Renato
źródło
7

Istnieje bardzo dobra analogia miejsca typu fast food, która najlepiej wyjaśnia model Node.js sterowany zdarzeniami, zobacz pełny artykuł, Node.js, gabinety lekarskie i restauracje fast food - Zrozumienie programowania sterowanego zdarzeniami

Oto podsumowanie:

Gdyby fast food był zgodny z tradycyjnym modelem opartym na wątkach, zamawiałeś jedzenie i czekałeś w kolejce, aż go otrzymasz. Osoba stojąca za tobą nie będzie mogła złożyć zamówienia, dopóki zamówienie nie zostanie zrealizowane. W modelu sterowanym zdarzeniami zamawiasz jedzenie, a następnie wychodzisz z kolejki i czekasz. Wszyscy inni mogą wtedy zamówić.

Node.js jest sterowany zdarzeniami, ale większość serwerów WWW jest oparta na wątkach. York wyjaśnia, jak działa Node.js:

  • Korzystasz z przeglądarki internetowej, aby poprosić o plik „/about.html” na serwerze internetowym Node.js.

  • Serwer Node.js przyjmuje żądanie i wywołuje funkcję pobierania tego pliku z dysku.

  • Podczas gdy serwer Node.js czeka na pobranie pliku, obsługuje następne żądanie sieciowe.

  • Po pobraniu pliku do kolejki serwerów Node.js wstawiana jest funkcja zwrotna.

  • Serwer Node.js wykonuje tę funkcję, która w tym przypadku wyrenderowałaby stronę „/about.html” i odesłała ją z powrotem do przeglądarki internetowej. ”

adeleinr
źródło
6

Cóż, rozumiem to

  • Celem węzła jest zapewnienie łatwego sposobu tworzenia skalowalnych programów sieciowych.
  • Węzeł jest podobny do projektu i pod wpływem systemów takich jak Ruby's Event Machine lub Python's Twisted.
  • Wystąpiło we / wy dla javascript V8.

Dla mnie oznacza to, że miałeś rację we wszystkich trzech założeniach. Biblioteka z pewnością wygląda obiecująco!

nes1983
źródło
1
Wiele razy znajduję się na stronie jest dość niejasna.
Jeff
6

Nie zapomnij też wspomnieć, że Google V8 jest BARDZO szybki. W rzeczywistości konwertuje kod JavaScript na kod maszynowy o dopasowanej wydajności skompilowanego pliku binarnego. Tak więc, wraz ze wszystkimi innymi świetnymi rzeczami, jest NIESAMOWICIE szybki.

Quinton Pike
źródło
3

Q: Model programowanie sterowane zdarzeniami, zwłaszcza sposób, w jaki obsługuje I / O .

Poprawny. Używa wywołań zwrotnych, więc każde żądanie dostępu do systemu plików spowoduje wysłanie żądania do systemu plików, a następnie Node.js rozpocznie przetwarzanie następnego żądania. Będzie martwił się tylko żądaniem We / Wy, gdy otrzyma odpowiedź z systemu plików, w którym to czasie uruchomi kod wywołania zwrotnego. Możliwe jest jednak wykonywanie synchronicznych żądań We / Wy (czyli blokowanie żądań). Deweloper może wybrać między trybem asynchronicznym (wywołania zwrotne) lub synchronicznym (oczekiwanie).

P: Używa JavaScript, a parser to V8.

tak

P: Można go łatwo wykorzystać do tworzenia współbieżnych aplikacji serwerowych.

Tak, chociaż będziesz musiał ręcznie napisać sporo kodu JavaScript. Lepiej byłoby przyjrzeć się ramom, takim jak http://www.easynodejs.com/ - która zawiera pełną dokumentację online i przykładową aplikację.

Charles
źródło