to może być modne, ale czy jest praktyczny powód do przyjęcia Node.js? Lee Boynton pokazuje, jak można go użyć, aby dodać kanał wiadomości w czasie rzeczywistym do witryny PHP.

Ten artykuł ma na celu pokazanie, w jaki sposób możesz zacząć używać Node do dodawania funkcji w czasie rzeczywistym do witryny opartej na PHP. Najpierw przyjrzymy się nieco bardziej temu, co sprawia, że Node dobrze nadaje się do aplikacji w czasie rzeczywistym, zanim przejdziemy do zademonstrowania, jak zbudować kanał wiadomości w czasie rzeczywistym i włączyć go do swojej witryny PHP.

Thread-based vs Event-based

tradycyjnie PHP jest obsługiwane przez Apache i moduł mod_php. Jeśli uruchomisz polecenie ’ top ’ na serwerze sieciowym opartym na systemie Unix, prawdopodobnie zobaczysz dużą liczbę procesów Apache obsługujących klientów sieciowych. W tej konfiguracji każde żądanie klienta zwykle wywołuje nowy proces Apache, dopóki nie zostanie zużyta cała dostępna pamięć RAM. Ostatnio nginx i php-FPM stały się najbardziej wydajną metodą obsługi stron PHP, ale nawet w tej konfiguracji każdy klient jest obsługiwany przez inny proces PHP. Kluczowym punktem jest to, że od początku do końca żądanie klienta wykorzystuje proces PHP przez cały czas. Jeśli przetwarzanie każdego żądania zajmuje dużo czasu, zasoby serwera mogą zostać wykorzystane bardzo szybko.

w węźle pojedynczy proces węzła zazwyczaj służy każdemu klientowi w pętli zdarzeń. W przypadku długotrwałych, kosztownych procesów, takich jak dostęp do systemu plików, bazy danych lub zdalnego API, zaleca się używanie asynchronicznych wywołań metod zamiast blokowania. Osiąga się to poprzez użycie wywołań zwrotnych, które są wyzwalane po zakończeniu akcji, takiej jak dostęp do systemu plików. Oznacza to, że pojedynczy proces węzła może nadal przetwarzać nowe żądania, podczas gdy kosztowna operacja jest wykonywana w tle. Po zakończeniu kosztownej operacji wraca ona do kolejki pętli zdarzeń, która ma być dalej przetwarzana przez węzeł.

zasadniczo węzeł może być postrzegany jako podobne środowisko do budowania aplikacji, takich jak Twisted Pythona lub EventMachine w Ruby. Node ma również wbudowany serwer HTTP gotowy do produkcji, więc nie potrzebuje oddzielnego serwera, aby go uruchomić, takiego jak Apache lub Nginx, dodatkowo zwiększając wymagania dotyczące lean resource (wykluczając wycieki pamięci).

var http = require('http');http.createServer(function (req, res) { res.writeHead(200, {'Content-Type': 'text/plain'}); res.end('Hello Worldn');}).listen(1337, '127.0.0.1');console.log('Server running at http://127.0.0.1:1337/');

powyższy przykład kodu pokazuje, jak można napisać obowiązkowy serwer WWW „hello world” w zaledwie kilku linijkach kodu. Pierwsza linia demonstruje użycie systemu modułów znanego jako CommonJS, którego Node używa do dołączania oddzielnych modułów. Funkcja require jest wbudowana i w tym przypadku importuje moduł http węzła do użycia w aplikacji. Druga linia tworzy nowy obiekt web serwera. Zauważ, że pierwszym parametrem metody createServer jest funkcja anonimowa. Większość metod w węźle akceptuje funkcję zwrotną jako parametr i jest to klucz do budowania aplikacji sterowanych zdarzeniami.

następną linią wykonania jest linia 5, która wykorzystuje łańcuch metod do wywołania metody listen na zwracanej wartości metody createServer (zwracaną wartością jest instancja modułu HTTP). Metoda listen powoduje, że serwer zaczyna przyjmować żądania HTTP na porcie 1337 na localhost. Ostatnia linia pisze wiadomość do konsoli z informacją, że serwer został uruchomiony. Tylko podczas żądania do serwera jest wywoływana funkcja anonimowa, która ustawia kod statusu HTTP na 200 OK i ustawia nagłówek Content-Type. Wiadomość „Hello World” jest w końcu zapisana do ciała odpowiedzi HTTP w linii 4.

dlaczego warto używać Node.więc js?

model node ’ a oparty na zdarzeniach jest szczególnie odpowiedni dla aplikacji czasu rzeczywistego, takich jak gry, kanały informacyjne i aplikacje do czatu. Ponadto pozwala również używać tego samego języka na interfejsie frontendowym i backendowym. JavaScript staje się coraz bardziej popularny, ponieważ tworzone są bardziej bogate aplikacje po stronie klienta, a przeglądarki internetowe szybciej wykonują JavaScript. Przełączanie się między językami może być frustrujące.

WordPress Spezial

Entwickler Magazin Spezial Vol. 10: WordPressEntwickler Magazin Spezial Vol. 10: WordPress
Alles rund um WordPress im Entwickler Spezial Vol. 10-ab 18.11.2016 im Handel.
WordPress ist längst weit mehr als ein simples Blogsystem. In diesem Sonderheft beschäftigen sich zahlreiche Spezialisten mit allen wichtigen Fragen rund um das verbreitetste CMS im Web; und dabei geht es nicht nur um klassische Themen, sondern auch um Affiliate Marketing, E-Commerce u.V.m.

Po drugie, ma dobre wsparcie dla websocketów. Chociaż możliwe jest wsparcie Websocketów w PHP, asynchroniczny charakter węzła i wbudowany serwer HTTP sprawiają, że jest on lepiej dopasowany. WebSockets to sposób na utrzymanie trwałego połączenia z przeglądarką w celu szybkiego przesyłania danych do klienta. W porównaniu z poprzednimi rozwiązaniami, takimi jak long polling czy comet, Websockety wiążą się z dużo mniejszym opóźnieniem, ponieważ nie ma narzutu na tworzenie instancji połączenia HTTP za każdym razem, gdy niektóre dane muszą być wysłane. Minusem WebSockets jest to, że jest to funkcja HTML5 i jako taka nie jest tak dobrze obsługiwana w przeglądarkach, jak zwykły stary Ajax. Można jednak z wdziękiem powrócić do alternatywnych technik, takich jak długie sondowanie w przeglądarkach, które nie obsługują Websocketów.

na tegorocznej międzynarodowej konferencji PHP można dowiedzieć się więcej na temat integracji węzłów.js z PHP!

Międzynarodowa Konferencja PHP jest pierwszą na świecie konferencją PHP i od ponad dekady jest punktem zwrotnym dla najwyższej klasy pragmatycznej wiedzy w zakresie PHP i technologii internetowych . Podczas IPC międzynarodowi eksperci z branży PHP spotykają się z użytkownikami PHP i programistami z dużych i małych firm. Sprawdź nasze ceny Early Bird dla wielkich rabatów!

oto kilka najważniejszych sesji z IPC:

  • dostęp do aplikacji js
    Dirk Ginader (Google)
  • TypeScript – dzięki czemu rozwój JavaScript jest bardziej wydajny i solidny
    Rainer Stropek (software architects gmbh)
  • Jak przygotować się do PHP 7
    Sebastian Bergmann (thePHP.cc)

pamiętaj jednak, że Node jest niedojrzałą platformą w porównaniu do PHP. Pierwotnie stworzony w 2009 roku, jest jeszcze w powijakach i nie osiągnął jeszcze wersji 1.0 – jeśli to ma dla ciebie znaczenie. Może się okazać, że interfejsy API, których używasz, zmienią się w przyszłości lub nie będziesz mógł znaleźć frameworka, który ma ten sam zestaw funkcji co twój ulubiony framework PHP. Rzeczywiście, z mojego doświadczenia wynika, że dostępne biblioteki i frameworki innych firm składają się z znacznie mniejszych pakietów funkcjonalności, które trzeba złożyć razem.

istnieje również większe ryzyko wycieków pamięci, które zatrzymają Twoją aplikację. Procesy Node zazwyczaj działają w sposób ciągły, podczas gdy procesy PHP mają tendencję do okresowego odradzania się, aby zniwelować efekt wycieków pamięci.

część integrująca

kanał wiadomości zostanie zintegrowany z podstawową stroną PHP, która obsługuje logowania i sesje użytkowników, przy użyciu wspólnej konfiguracji php-fpm i nginx. Będziemy używać JavaScript do komunikacji z aplikacją węzła po stronie serwera i dynamicznie aktualizować kanał wiadomości bez przeładowywania strony. Najpierw jednak krótka przerwa na sesje.

Jeśli jeszcze tego nie robisz, powinieneś używać scentralizowanego obszaru przechowywania dla swoich sesji (Rysunek 1). Memcached może być łatwo użyty do tego zadania przy użyciu wbudowanej procedury zapisywania sesji w rozszerzeniu PECL memcached. Jeśli chcesz ponownie uruchomić serwer przechowujący sesje bez utraty danych, Redis jest dobrym wyborem. Tak czy inaczej, scentralizowana pamięć masowa sesji umożliwia równoważenie obciążenia aplikacji na wielu serwerach internetowych. Umożliwia również udostępnianie danych sesji aplikacjom zbudowanym w innych językach programowania.

Rysunek 1: wspólna Architektura sesji.

istnieje jednak mały problem z analizowaniem danych sesji. Poniżej znajduje się domyślny format serializacji sesji PHP:

not|a:2:{i:0;s:4:"easy";i:1;a:1:{s:2:"to";s:5:"parse";}}

może się wydawać, że można użyć manipulacji łańcuchami, aby je przeanalizować, ale mogą istnieć przypadki krawędzi, które są trudne do rozwiązania. Byłoby miło, gdyby sesja była serializowana w bardzo lubianym formacie JSON:

{"this":{"is": "easier", "to": "parse"}}

znacznie lepiej. Dość łatwo jest napisać własny serializer sesji, który przekonwertuje to, co przechowujesz w formacie $_SESSION na format JSON, zobacz moją wersję.

Alternatywnie, możesz rozważyć msgpack, który może być skonfigurowany do serializacji sesji, jak w poniższym kodzie, który również pokazuje, jak używać memcached jako procedury obsługi zapisu sesji.


dla węzła dostępna jest biblioteka innej firmy, która może serializować i deserializować msgpack, dostępna w npm (Menedżer pakietów węzła, zawiera dużą liczbę modułów, które można wykorzystać w aplikacji za pomocą prostej instalacji npm ). Przyjrzymy się teraz budowaniu kanału informacyjnego za pomocą węzła i włączeniu go do aplikacji PHP.

aplikacja PHP

aplikacja PHP po prostu obsługuje logowanie użytkowników i sesje. Sesje są przechowywane w memcached, ale mogą być łatwo przechowywane w redis. Poniższy kod pokazuje fragmenty prostej aplikacji ONE page (aby uzyskać pełne źródło przejdź do github.com/lboynton/phphants-march-php).

// // <!]>

pierwsza linia skryptu zawiera plik autoloadera Composera, co oznacza, że wszystkie zależności są automatycznie ładowane, co eliminuje potrzebę oddzielnego dołączania lub wymagania linii (Uwaga edytora: więcej o Composerze, patrz Jefersson Nathan de O. Artykuł Chavesa). W tym przypadku obsługa zapisu sesji jest jedynym wymaganym fragmentem kodu zewnętrznego. Jednak bardzo łatwo jest dołączyć Pakiety innych firm dostępne na packagist lub w innym miejscu w późniejszym terminie za pomocą Composera, który również zostanie automatycznie dodany do automatycznego ładowania. Linie 3 i 4 konfigurują połączenie z memcached, podczas gdy obsługa zapisu sesji jest inicjowana i rejestrowana w PHP w liniach 5-14. Użytkownicy są logowani po prostu przez podanie nazwy użytkownika jako parametru GET, chociaż w prawdziwym systemie powinno to zostać zastąpione bardziej funkcjonalnym systemem uwierzytelniania.

Po stronie JavaScript używamy zewnętrznych bibliotek : jQuery, underscore.js i Socket.IO klient, który jest przeglądarkową częścią modułu węzła, którego będziemy używać do wysyłania danych do przeglądarki. Io.wywołanie metody connect tworzy połączenie z aplikacją węzła, która może korzystać z jednego z wielu transportów, takich jak websockets lub Ajax w zależności od obsługi przeglądarki. Gniazdo.metoda on ustawia procedurę obsługi zdarzenia, która będzie renderować element wiadomości na stronie, gdy zdarzenie’ news ’ zostanie wywołane przez stronę serwera.

Uwaga: Aplikacja używa Composera do instalacji programu session save handler i Bowera, menedżera pakietów do instalacji zasobów po stronie klienta. Aby zainstalować Bower, Uruchom „npm-g install bower”. Następnie, aby zainstalować aktywa, wykonaj „bower install”. Alternatywnie, zaktualizuj znaczniki skryptu i arkusze stylów o wersje lokalne.

aplikacja jest obsługiwana za pomocą nginx. Poniżej znajduje się plik konfiguracyjny nginx:

upstream node { server localhost:3000;}server { listen 8080; server_name php-node-demo.localhost; root /home/lee/public_html/php-node-demo; index index.php; location / { try_files $uri $uri/ /index.php?$args; } location ~ .php$ { include fastcgi_params; fastcgi_index index.php; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } location ~ /socket.io { proxy_pass http://node; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }}

linie 1-3 definiują serwer upstream, który uruchamia aplikację Node. Wszelkie prośby kończące się na .php zostanie wysłane do php-fpm (linie 15-20), podczas gdy wszelkie żądania z /socket.io w adresie URL zostanie przekazane do aplikacji węzła (linie 22-27). Linie 25 i 26 mówią nginx, aby obsługiwał przełączanie protokołów i umożliwiał proxy websocketów do węzła. Oznacza to, że zarówno aplikacja PHP, jak i aplikacja Node są uruchamiane na tym samym porcie, jeśli chodzi o klienta.

js App

węzeł.aplikacja js po prostu obsługuje wszelkie żądania klientów dotyczące kanału informacyjnego. Jego fragmenty są wyświetlane poniżej (patrz github.com/lboynton/phphants-march-node dla pełnego źródła).

io.set('authorization', function(handshake, callback) { var cookies = cookie.parse(handshake.headers.cookie); mcClient.get('sessions/' + cookies.PHPSESSID, function(error, result) { if (error) { callback(error, false); } else if (result) { handshake.session = JSON.parse(result); callback(null, true); } else { callback('Could not find session ID ' + cookies.PHPSESSID + ' in memcached', false); } });});io.sockets.on('connection', function(socket) { var session = socket.handshake.session; sockets = socket;);function getNews() { redis.blpop('news', 0, function(err, data) {news = JSON.parse(data);if (typeof news.to !== 'undefined') { if (typeof sockets !== 'undefined') {sockets.emit('news', news.content); }} else { io.sockets.emit('news', news.content);}process.nextTick(getNews); });}

Gniazdo.io jest biblioteką, która dostarcza pojedynczy API do wykonywania komunikacji WebSocket między Klientem a serwerem. Obsługuje również wdzięczne Awaryjne, gdy WebSocket nie jest dostępny w przeglądarce, i inne przydatne funkcje protokołu wiadomości, takie jak bicie serca, timeouts i wsparcie rozłączania, które nie jest obsługiwane po wyjęciu z pudełka z API WebSocket HTML5.

pierwszy urywek konfiguruje autoryzację dla żądań, które Socket.io odbiera. Gdy pojawi się nowe żądanie, przetworzy pliki cookie w żądaniu i spróbuje pobrać klucz memcached, który odpowiada wartości pliku Cookie PHPSESSID (domyślna nazwa pliku cookie sesji PHP). Jeśli zostanie znaleziony, będzie przechowywał wartość parsowanego klucza memcached w danych.sesja, do której można uzyskać dostęp później.

następny fragment konfiguruje, co powinno się wydarzyć, gdy Socket.io wyzwala zdarzenie 'connection’. To zdarzenie jest wyzwalane podczas początkowego połączenia z klientem, po autoryzacji. Dane sesji, które zostały wcześniej pobrane z memcached, można teraz odwoływać się przez gniazdo.zmienny uścisk dłoni. Gdy klient łączy się, instancja gniazda jest powiązana z nazwą użytkownika klienta, dzięki czemu wiadomości mogą być wysyłane do poszczególnych użytkowników.

ostatni fragment zawiera funkcję sprawdzania nowych wiadomości w kolejce redis. Używa polecenia BLPOP w redis, co oznacza, że jeśli kolejka jest pusta, zostanie zablokowana, dopóki niektóre dane nie zostaną dołączone do kolejki przed jej uruchomieniem. Gdy niektóre dane mogą zostać usunięte z kolejki, są one przetwarzane jako JSON przed określeniem, czy zawartość powinna zostać wysłana do każdego podłączonego klienta, czy tylko jednego użytkownika. Zawartość wiadomości jest wysyłana do właściwego gniazda przez wywołanie metody emit () na gnieździe, które było wcześniej powiązane z użytkownikiem w procedurze obsługi zdarzeń połączenia.

wreszcie proces węzła.metoda nextTick() jest wywoływana z funkcją getNews jako argumentem. Oznacza to, że funkcja getNews zostanie wywołana przy następnym uruchomieniu pętli zdarzenia i będzie nadal sprawdzać kolejkę redis dla danych aż do zatrzymania aplikacji.

aby zainstalować, użyj npm, aby pobrać wymagane zależności. Następnie uruchom aplikację za pomocą aplikacji node.js.

powinieneś teraz otworzyć przeglądarkę internetową i przejść dohttp://localhost:8080/?username=bob I zobaczyć aplikację News feed. Teraz otwórz drugą kartę przeglądarki lub okno z inną nazwą użytkownika, na przykład http://localhost:8080/?username=sally.

aktualizacja kanału

aktualizacja kanału jest po prostu przypadkiem wciśnięcia nowego newsa do kolejki. Połącz się z interfejsem redis CLI za pomocą polecenia redis-cli. Jest to interaktywna powłoka dla redis, pozwalająca na bezpośrednie wysyłanie poleceń do serwera. Poniższy przykład kodu pokazuje, jak przejść do kolejki:

rpush news '{"content": "Testy test", "to": "bob"}'

w oknie przeglądarki internetowej, które otworzyłeś dla użytkownika bob, powinieneś zobaczyć element wiadomości przesunięty z góry strony. Alternatywnie, możesz wypchnąć Wiadomości do Boba, sally i wszystkich innych podłączonych klientów, wykluczając parametr „to”, w następujący sposób:

rpush news '{"content": "Everyone should see this"}'

w prawdziwej aplikacji można wypchnąć dane do kolejki z PHP, używając na przykład Rozszerzenia php-redis lub predis.

wnioski

to tylko prosty przykład, aby zademonstrować, w jaki sposób Node może być zintegrowany z Twoją aplikacją PHP. Istnieje kilka ograniczeń w realizacji. Na przykład zapamięta tylko jedno połączenie od każdego użytkownika. Dlatego jeśli użytkownik ma wiele kart lub okien otwartych dla kanału wiadomości, tylko jedna strona zostanie zaktualizowana. Można to rozwiązać, przechowując tablicę gniazd na użytkownika i śledząc każde połączenie i rozłączenie, aby dodać lub usunąć gniazda z tablicy. Czytelnikowi pozostaje wdrożenie lepszego rozwiązania. Pokazał również narzędzia takie jak Composer i Bower, które Gorąco polecam rozważyć użycie w swoich aplikacjach.

Lee Boynton jest programistą z siedzibą w Hampshire w Wielkiej Brytanii, ze szczególnym zainteresowaniem aplikacjami czasu rzeczywistego, takimi jak komunikatory i strumienie aktywności. Posiada wiedzę na temat rozwoju i administracji po stronie serwera, a także rozwoju frontendu. Pracuje w lokalnej firmie Symbios Group, jest także członkiem PHP, dla której pomaga w organizacji imprez.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany.