Nasza strona używa cookies. Dowiedz się więcej o celu ich używania i zmianie ustawień w przeglądarce. Korzystając ze strony, wyrażasz zgodę na używanie cookies, zgodnie z aktualnymi ustawieniami przeglądarki. Rozumiem

Czy Node.js już na zawsze pozostanie powolną wersją Golanga?

Alex Hultman uNetworking
Prezentacja bibliotek µSockets i µWebSockets.js, które znacznie przyspieszają Node.js.
Czy Node.js już na zawsze pozostanie powolną wersją Golanga?

Wydawałoby się, że nie ma dnia bez ogłoszenia jakiegoś nowego, rzekomo szybszego "webowego frameworka" dla Node.js. Tak, wszyscy wiemy, że Express jest powolny, ale czy może kolejny "webowy framework" może poprawić wydajność I/O? Nie, raczej nie ma takiej możliwości. Aby sięgnąć dalej, należy sięgnąć głębiej i zaprojektować coś od nowa, a nie tylko nałożyć nową warstwę na oprogramowanie.

Express jest jednym z najstarszych, tzw. "webowych frameworków" dla Node.js. Opiera się on na tym, co dostarcza sam Node.js, dodając ładny appko-centryczny interfejs do zarządzania routingiem, parametrami, metodami i tym podobnymi.

Jest produktywny i elegancki - to na pewno, ale brakuje mu wydajności. Tymczasem pojawiają się projekty takie jak Fastify i setki podobnych. Wszystkie mają na celu zapewnienie tego samego, co Express, ale z mniejszą stratą wydajności. Ale mniejsza strata, to wciąż strata. To nie jest rozwiązanie. Te projekty są nadal ściśle ograniczone tylko do tego, jakie możliwości ma Node.js, a jest ich niewiele w porównaniu z konkurencją:

Żaden "webowy framework" dla Node.js, bez względu na to, czy to Fastify, czy nie, nie może przekroczyć czerwonej linii. To jest bardzo nisko postawiona górna granica w porównaniu z modnymi alternatywami, takimi jak Golang.

Na szczęście Node.js obsługuje rozszerzenia C++, wiązania Google V8, które łączą JavaScript z C++ i pozwalają JavaScript wywołać wszystko, co oferuje sam Node.js, a nawet jeszcze więcej.

Umożliwia to rozszerzenie i ponowne zdefiniowanie tego, co można zrobić z JavaScriptem. Node otwiera się na JavaScript, który działa w pełnym zakresie umożliwionym przez Google V8, nie ograniczając się do tego, co "programiści Node.js" uznali za wystarczająco dobre.


Wypuszczenie nowego µWebSockets.js

Udostępniam zupełnie nowy kod, µWebSockets.js, dostępny na GitHubie:

  • Zainstaluj go na Node.js przy użyciu NPM (mimo że jest hostowany na GitHubie): npm install uNetworking/uWebSockets.js#v15.0.0, rzuć okiem na dokumenty instalacyjne NPM.
  • Nie wymaga kompilatora; Linux, MacOS i Windows. Zaczynamy od wersji 15.0.0 i uaktualniamy zgodnie z SemVer.


Jest to alternatywny serwer webowy dla backendu JavaScript, napisany w ~6 tys. linii C i C++, znacznie przewyższający pod względem wydajności Golang. Bitfinex.com sortowało oba swoje API tradingowe (REST & WebSocket) i obecnie stopniowo wprowadza je na produkcję.

Paolo Ardoino z Bitfinex chciał tylko wtrącić, że "to cholernie fajny projekt".

Praca ta jest możliwa wyłącznie dzięki sponsorom; BitMEX, Bitfinex i Coinbase umożliwiły tę pracę. Dzięki nim mamy teraz nowe wydanie!


Proszę mi wyjaśnić, o co w tym wszystkim chodzi?

Jest to nowy projekt, z licencją Apache 2.0, następca tego, co jest znane jako "uws". Jest to cały stos, od jądra systemu operacyjnego do Google V8, kompletny bypass, który zapewnia stabilne, bezpieczne, zgodne ze standardami, szybkie i lekkie I/O dla Node.js:

W tym warstwowym podejściu, gdzie każda warstwa zależy tylko od poprzedniej, bardzo łatwo jest śledzić i naprawiać problemy i/lub rozszerzać je o nowe wsparcie.

µSockets sam posiada trzy podwarstwy, przechodząc od eventingu przez networking do crypto, przy czym każda z nich jest świadoma tylko poprzedniej. Dzięki temu można wymieniać części, naprawiać błędy, dodawać alternatywne implementacje bez zmiany wysokopoziomowego kodu.

Masz dość OpenSSL? W porządku, zamień go przez wymianę ssl.c i jego 600 linii kodu. Żadna inna warstwa nie wie nawet czym jest SSL, więc błędy są łatwe do zlokalizowania.


Wewnętrzne podwarstwy µSockets

Różni się to znacznie od tego, jak implementowany jest Node.js, z jego koncepcją "wszystko-wszędzie-naraz". W jednym pliku źródłowym Node.js można znaleźć połączenia libuv, wywołań systemowych, wywołań OpenSSL, czy V8. To wszystko jest tworzy wielki bałagan bez poczucia odosobnionego celu. Jest to powód dla którego tak trudno dokonać znaczących zmian.


Kodowanie z µWebSockets.js, w pigułce

To, co zobaczysz poniżej, to wielkie uproszczenie i wiele koncepcji jest pominiętych dla zwięzłości, ale powinno dać Ci wyobrażenie o tym, czym jest µWebSockets.js:

Pod pewnymi względami możliwe jest osiągnięcie dużo lepszych wyników niż z Golang Gorilla WebSockets w pojedynku SSL vs brak SSL. Oznacza to, że Twój kod JS na SSL może wysyłać wiadomości szybciej niż Golang może bez SSL (w niektórych przypadkach). Moim skromnym zdaniem to całkiem fajna sprawa.


Szybkie wsparcie dla pub/sub

Socket.IO jest pod wieloma względami odpowiednikiem Express, tylko w czasie rzeczywistym. Oba są dojrzałe, eleganckie i popularne, ale również bardzo powolne:

Większość tego, co Socket.IO faktycznie robi, można sprowadzić do pub/sub, funkcja wysyłania wiadomości do pokoju z wieloma odbiorcami i odbierania ich w podobny sposób.

Fallbacki są dziś całkowicie bezcelowe, ponieważ każda przeglądarka obsługuje (i to od dawna) WebSockets. Ruch SSL nie może być interpretowany przez korporacyjne proxy i będzie przechodzić przez sieć dokładnie tak samo, jak każdy inny ruch HTTP, więc WebSockets po SSL na pewno nie będzie blokowany. Wciąż można mieć fallbacki, ale są one bezcelowe i powodują niepotrzebną złożoność.

Jednym z celów z µWebSockets.js jest zapewnienie funkcji podobnych do tych, które można znaleźć w Socket.IO, aby ułatwić całkowitą zamianę, bez dodatkowego opakowywania. A to wszystko, nie egzekwując jednocześnie żadnego konkretnego protokołu niestandardowego.

Wiele firm, tak naprawdę większość, boryka się z jakimś problemem pub/sub, jeśli chodzi o WebSockets. Niestety, wydajny pub/sub nie zmieścił się w obecnym wydaniu, ale wkrótce nadejdzie. Priorytet jest bardzo wysoki. I będzie naprawdę szybki (benchmarki wskazują na to, że może być szybszy niż Redis). Wypatruj go!


Co dalej?

Dopracowywanie, dodawanie funkcji i korygowanie błędów. Na pewno początkowo nie wszystko będzie pasować idealnie. Pamiętaj jednak, że jest to duży projekt składający się z wielu tysięcy linii C++ i C rozwijanych w trzech różnych repozytoriach:


Projekt ten jest wykorzystywany przez firmy z dużym obłożeniem I/O. Stabilność i bezpieczeństwo jest najwyższym priorytetem tego projektu. Upewnij się, że zgłaszasz nam wszystkie problemy ze stabilnością we wczesnych wydaniach, gdy możemy je wprowadzić w dużych poprawkach.

Jeśli jako firma uważasz, że ten projekt ma sens i leży w Twoim interesie ekonomicznym, skontaktuj się ze mną. Zajmuję się konsultingiem itp., na różne sposoby. Kontakt do mnie: https://github.com/alexhultman


Oryginał tekstu w języku angielskim przeczytasz tutaj.

Masz coś do powiedzenia?

Podziel się tym z 120 tysiącami naszych czytelników

Dowiedz się więcej
Rocket dog