Node js

Ostatnio można zaobserwować dość duży hype wokół Node.js.

To mnie jednak jakoś szczególnie nie zdziwiło.
Zdziwiło mnie natomiast to, że przeglądając oferty pracy RoR np z elance, coraz częściej Node.js pojawia się jako ‘obligatory’ czyli znajomość obowiązkowa.

Mógłby ktoś wymienić kiedy i gdzie opłaca się stosować kombo RoR + Node.js?
Jakie są zastosowania? itp

Edycja:
LOL. W końcówce tematy jest *.js i nginx próbuje serwować plik JS.
Przydało by się by moderator zmienił nazwę tematu na “Node js” żeby nie wywalało takimi errorami. :stuck_out_tongue:

[quote]Mógłby ktoś wymienić kiedy i gdzie opłaca się stosować kombo RoR + Node.js?
Jakie są zastosowania? itp[/quote]

  1. Systemy czasu rzeczywistego, gdy chcesz zminimalizować opóźnienia i obsługiwać tysiące requestów na sekundę.
  2. Przypadki długiego czekania na I/O (np. upload pliku), w Railsach zwykle wtedy cały proces zżerający +100MB ramu wisi i czeka, oparte na eventach Node.js podczas czekania na I/O nie pożera żadnych zasobów.

@Mathias:
Node jest złem, czystym złem. Żeby nie było śledziłem postępy, próbowałem kilku aplikacji, oraz sam napisałem kilka małych aplikacyjek w node.js. I wydaje poinformowaną opinię: node.js jest złem, pisanie w javascripcie na serwerze jest masochizmem, a reklamowanie node.js jako przydatnego do czegokolwiek jest sadyzmem.

Technologię warto znać, szczególnie że teraz jest na nią hype, i można wcześnie wskoczyć i zarobić tony pieniędzy na idiotach którzy chcą mieć coś napisane w technologii która jeszcze nie wyszła z bety i z każdym releasem 0.x zmienia się tak że połowa programów przestaje działać.

hahaha, ale pocisk :smiley:

To w sumie puste słowa. Zero rzeczowych i konkretnych argumentów.

Proszę, masz rzeczowy argument: w Node.js część błędów programisty (składniowych itd.) powoduje rzucenie wyjątkiem, a część powoduje zamknięcie procesu z błędem. A teraz sobie przedstaw że ów “proces” to twój serwer aplikacji.

Technologia jest obiecująca, ale moim zdaniem na razie do niczego co “ma działać” się nie nadaje, przy czym powód powyższy uważam za ultimate cockblocker. Utrzymanie kodu w stylu callback-spaghetti też dość szybko robi się koszmarne.

Czuję flamewar. :stuck_out_tongue:

Czytałem takich trochę, na takich wnioskach się zakończyło:

Problem 1: czy zastąpić Railsy (lub ich część) czymś eventowym?
Ma to sens:

  • dla małych aplikacji które mają być wydajniejsze niż Sinatra,
  • dla ratowania wydajności przy długim czekaniu na I/O,
    nie ma dla:
  • typowych webaplikacji i ich API,
  • bardzo dużych systemów “enterprise”.

Problem 2: czy na eventowy framework wybrać Node.js?
Za:

  • Javascript, czyli możliwość dzielenia kodu między klientem i serwerem,
  • nie ma blokujących blibliotek,
    Przeciw:
  • Javascript to zło,
  • technologia w wersji beta.

W pozostałych kryteriach nie ma znaczących różnic pomiędzy możliwymi drogami…

No ale: jeżeli ktoś wykonuje długotrwałe I/O w wątku/procesie aplikacji webowej, to jest po prostu głupi. Node.js go z tego nie wyleczy, co najwyżej przykryje, a i to do czasu :wink:

Widzieli? http://railwayjs.com

S
Z
O
K

jak to zapierdziela.

Konkretnie, jak wspomniał Tomash, niektóre wyjątki są niełapalne i powodują natychmiastowy pad aplikacji(sic!).
Najlepsze jest to że do niedawna nie było sposobu żeby temu zapobiec. Jeden jedyny niezłapany wyjątek w którejś z bibliotek, kiedyś przy jakiejś okazji doprowadzi do wypierdzielenia aplikacji, i tak co kilka dni (albo godzin). Jako wisienka: nawet jak znajdziesz metodę która nie łapie wyjątku, nie ma szans na zbadanie ścieżki która doprowadziła do jej wywołania! :smiley:
Problemów z samą platformą jest tony, platforma potrafi się wywalać co jakiś czas bez powodu.

Idziemy dalej.
Styl tworzenia oprogramowania jest absurdalny. Jeżeli platforma wymusza na tobie konkretne zachowania typu
if(err){ throw(err) }
na początku każdej funkcji to jest to smród. Analizowałem swój własny kod, ponad 20% mojego kodu to był boilerplate. Bezużyteczne komendy pozwalające np. na łapanie wątków z callbacków, jak tego nie zrobisz, to wołasz asynchroniczne czytanie pliku, plik rzuca wyjątek, a ty nie masz pojęcia z jakiego powodu plik był w ogóle ładowany.
Zobacz sobie jak wygląda moduł fs nie ma to jak superobiekt, i programowanie strukturalne.

Zresztą widać to po stackoverflow.com. Obejrzyj sobie tag node.js i zobacz ile ludzi ma problemy z najprostszymi rzeczami, obsługą wyjątków, obsługa plików.
Ludzie głowią się godzinami jak sprawdzić np który plik jest najnowszy. W ruby sprowadza się to do Dir["*"].map{|x| File.mtime(x)}.max
Teraz napisz mi to samo w node.js w trybie asynchronicznym :smiley: Podpowiedź będziesz miał problem bo:
a) w node.js nie ma obsługi glob w bibliotece standardowej
b) nie ma wbudowanej obsługi synchronizacji, więc nie ma łatwego sposobu żeby zsynchronizować ze sobą x wątków.
Kod do zrobienia podobnego zadania (sprawdzenie czy najnowszy plik źródłowy jest nowszy od wyjściowego) rozciąga się w kompilatorze coffeescript na 9 linijek! (a i to tylko dlatego że w jednym miejscu użyli wywołania synchronicznego).

Możesz oczywiście użyć metody statSync no ale przecież w node.js wszystko ma być na callbackach prawda? no bo jak robisz sync, to blokujesz cała maszynę wirtualną.
Możesz oczywiście zainstalowac jedną z ponad 10 bibliotek do synchronizacji - każdą ze swoimi własnymi problemami i błędami. Możesz też doinstalować bibliotekę do globa, no ale po cholere się tak męczyć.

Co do dokumentacji - jeżeli myśleliście że stdlib ruby jest źle udokumentowany, to nie widzieliście jeszcze dokumentacji node.js. Niektóre parametry wejściowe/wyjściowe nie są w ogóle opisane i trzeba się domyślać bazując na wynikach man dla poleceń systemowych.

Na sam koniec - ludzie JAVASCRIPT, serio? Jest tysiące powodów dlaczego nikt nie lubi w tym programować. A teraz jeszcze programować w tym na serwerze? bez jaj.

Tak więc konkluzja: node.js jest dla masochistów, amatorów, i idiotów.

Polecam też:
http://teddziuba.com/2011/10/straight-talk-on-event-loops.html
i ciąg dalszy: http://teddziuba.com/2011/10/straight-talk-on-event-loops.html

PS. W odpowiedzi na pytanie kiedy należy stosować: NIGDY. Jak bardzo chcesz się paprawć w eventy to polecam EventMachine w Ruby.
Ewentualnie epoll w c.

Zasadniczo to co Świstak napisał (NECKBEARDS UNITED), z dwoma punktami niezgody:

  1. Javascript potrafi być fajny. To jest bardzo ciekawy język, a to że developerzy nie lubią w nim robić jest po prostu winą IE (lub niedouczenia developerów, którzy przed odrobieniem pracy domowej z teorii języka biorą się za pisanie kodu). Bardzo chciałbym pisać server-side javascript. Ale na pewno nie w Node.js, a na pewno nie w takim jaki jest teraz.

  2. Podpieranie się Tedem Dziubą w poważnej dyskusji jest automatyczną przegraną bez rzutu obronnego :wink:

Znaczy, nie dissuję Node.js jako pomysłu – bo pomysł jest fajny. Ale to, jak aktualnie Node.js implementuje ten pomysł, jest dla mnie nie do przyjęcia. Ale oczywiście jak ktoś lubi, to proszę bardzo – każdemu jego porno.

JS jest fajny (nie cały co prawda…), to DOM ssie. Jak ktoś jednak szuka czegoś na serwer, to może Erlang albo Clojure.

@Świstak: w Introduction to Node.js with Ryan Dahl Ryan ma świadomość powagi sytuacji i nie ukrywa, że brak backtrace’a przy błędach jest to blocker no. 1 przyszłości projektu.

Na chwilę obecną, nawet z tak cukierkowymi (choć również we prenatalnej fazie) polewami w postaci framework’ów, Node.js nie nadaje się do tworzenia aplikacji.

ZA TO, imo, z racji szybkości świetnie nadaje się do poprawy wydajności w wąskich gardłach aplikacji, gdy jest to konieczne - realny przykład.

A takie combo rails-redis-nodejs-webservices i praktycznie live-update treści na stronie, bez pochłaniania zasobów, mnie osobiście wzruszyło :slight_smile: >> Live Applications. Można prościej i wydajniej?

Cały sęk nodejs tkwi w wydajności (75% szybszy od statycznych stron via apache) i tyle - ot świetny pomocnik do odciążenia serwera w newralgicznych punktach aplikacji lub do jakiś bździnkowych serwisików. Dobrze znać.

Imho ten “realny przykład” jest bez sensu :wink: Kolesie porównują (jak to zwykle bywa) jabłka z gruszkami.

Tutaj nie chodzi o szybkość tylko o skalowalność, więc porównywanie 30 (ciężkich) aplikacji railsowych, które jak wnioskuję z artykułu mają wyłączone threadsafe!, z jakąś 100 linijkową aplikacją na node.js, we frameworku przypominającym sinatrę, można spokojnie zignorować jako mało miarodajne. Jak chciałbyś to uczciwie porównać, to trzeba by przepisać tą część wypakowaną do node na sinatrę, albo lepiej na jakiś asynchroniczny framework i wrzucić to na eventmachine.

Z ciekawości zrobiłem prosty benchmark sinatra vs express. Założenia:

  • akcja ‘/’, która zwraca string “hello world”
  • aplikacja siedzi za nginxem (tutaj niestety dałem trochę fory sinatrze, bo nie mogłem zmusić node do poprawnego utworzenia socketa, a już później nie chciało mi się zmieniać configu nginxa :wink: )
  • node 0.6.3, ruby 1.9.3
  • ab z dużymi wartościami “concurrency” (np. 50 lub 100)

Od razu napiszę, że benchmark jest zrobiony niechlujnie, ab jest odpalane na tym samym serwerze, nie mam zielonego pojęcia czy da się lepiej odpalić express, więc prosiłbym o nieprzywiązywanie do niego zbyt dużej wagi. Zresztą to hello world, więc też dużo nie powie. Chciałem tylko zobaczyć czy rzeczywiście ten node taki ZOMG szybki.

Sinatra na unicornie z 1 workerem wyciągnęła ok. 18k req/s. Z 4 workerami ok. 10k req/s.

Jakby ktoś się zastanawiał skąd ta różnica, to na 99.9% dlatego, że requesty są tak proste, że koszt dzielenia requestów pomiędzy workery zaczyna mieć znaczenie.

Express z 1 workerem ok. 20k req/s. Nie mam zielonego pojęcia jak odpalić jakiś cluster expressów lub odpalić kilka instancji node’a, więc jak ktoś ma większe doświadczenie i mu się chce, to proszę bardzo.

Czyli node.js zmiażdżył sinatrę o całe 2k requestów :wink: Tak jak napisałem, to był tak benchmark “na szybko” i mogłem przy tym popełnić jakiś mega błąd (tzn. np. uruchamiać express w jakiś sposób, w który się tego produkcyjnie nie robi), ale podejrzewam, że może to być zbliżone do rzeczywistości, tzn. node pewnie jest szybszy, ale raczej nie aż tak dużo jak niektórym się wydaje. Nie przeczę też oczywiście, że prawdopodobnie przy zwiększaniu obciążenia, ruby się szybciej wysypie niż node. Chciałem tylko podkreślić, żeby najpierw sprawdzać rozwiązania leżące najbliżej (ten sam język, nie trzeba zbyt dużo przepisywać ani używać technologii w wersji beta) zamiast uciekać się do czegoś szybszego, być może to wcale nie jest potrzebne.

Czy node.js nadal ma problemy z alokacją pamięci powyje 1 GB ? :stuck_out_tongue:

Jak już jesteśmy przy benchmarkach - wspomniany przeze mnie Erlang vs nodejs, czyli można i szybciej i stabilniej. Ktoś mi wyjaśni skąd ten hype wokół node’a? Bo nie trzeba się uczyć nowego języka?

Zamień to na “nie trzeba się uczyć Erlanga” i tak, właściwie tak.

Panowie nikt zwięźlej nie przekazał istoty node.js jak ten koleś tutaj w teście: Node.js Has a Bright Future.

So, why was Node.js so fast?
Most HTTP servers open a socket and spawn a thread for each request, or they at least maintain a pool of threads or processes. Node.js does not do this. Instead, there is one thread running an event loop which executes callbacks. Therefore, for each request, only a small heap allocation is needed, rather than a separate thread or process. Not only is it much faster to create only a small heap allocation, it also leaves a much smaller memory footprint.

A tu najbardziej techniczna prezentacja autora jaką znalazłem - na Google Tech Talk 2010.

Hype po części wziął się stąd, że na początku Ruby miał poważne problemy z wydajnością. Większość twierdziła, że wątki są złe a jedyną alternatywą było EM.Prawda była taka, że wątki były źle zaimplementowane w MRI 1.8 i to trwało przez lata co wywołało poszukiwanie alternatyw. We wszystkich benchmarkach asynchroniczne frameworki biły wątki na głowę (oczywiście tylko w środowisku Ruby - nie zawsze poza nim). Teraz dużo z tych osób co uwierzyło w twierdzenie “async or die” zainteresowało się rzeczami typu node.js i tkwi w przekonaniu, że to panaceum na wszystko. Stąd się bierze obecnie cała dyskusja typu “node.js szybsze o 75% niż statyczny apache - powyżej” (mam nowego avatarka na forum dzięki niemu ) i masa dyskusji w “środowisku”. Podczas gdy te burzliwe dyskusje się toczą, rzeczy takie jak pozbycie się GIL’a w RBX czy skupienie na tworzeniu wysoce wydajnych wielowątkowych serwerów w Ruby przechodzą bez większego rozgłosu. Ludzie wolą dyskutować o tym jak zoptymalizować fib w node przez memoization lub czy “hello world” wyciągnie 5k więcej requestów niż w Ruby niż skupić się na wielowątkowych rozwiązaniach realnych problemów, które stosowane są od lat i umożliwiają wykorzystanie nowoczesnych wielordzeniowych procesorów. Co zrobić, takie życie.

Ja osobiście nie narzekam, jak przyjdzie mi ochota na optymalizację ciągu fibonacciego i napisanie web-service który obsłuży 20k zapytań o 14-tysięczną liczbę nie będę miał wątpliwości jaką technologię wybrać, tymczasem wracam do bardziej przyziemnych problemów w Ruby.

Pamiętacie taki serwer www jak Ebb ? Też autorstwa Pana Ryana Dhala. Pamiętacie swiftyply, czy 3 tony innych serwerów które powstały na fali hype’a pisania coraz szybszych serwerów www?

Benchmarki frameworków/serwerów są najczęściej nic nie warte. Z mojego doświadczenia ZAWSZE ale to ZAWSZE winna jest sama aplikacja.
A jak ktoś chce szybkości to niech przepiszę część kodu w C lub C++ (piszę to serio), a nie w javascripcie!.

Co do Javascript, pisze w nim już kilka lat i mam wyrobioną osobistą opinię dlaczego javascritp (a nie dom!) ssie. W wolnej chwili napisze coś o tym więcej, a na razie polecam to zdjęcie które pięknie ilustruje mój pogląd: http://img.anongallery.org/img/2/0/javascript-the-good-parts-the-definitive-guide.jpg

PS. Nie cytowałem Pana Dziuby, ale dałem do niego linki ze względu na drugi post który formalnie udowadnia że model wątkowy wygrywa z wyjątkowym dla każdego przypadku w którym czas przetwarzania zapytania > czas utworzenia wątku.