Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: live chat i websocket, wydajny chat
Forum PHP.pl > Forum > PHP
bialko0019
Witam. CHciałbym stworzyć w miare wydajny ( zakładam około 5tyś userów dziennie, z czego np. 1/4 będzie używała wiadomości w danym dniu ) i chciałbym zrobić chat dla nich. Jak myślicie, serwer wytrzyma połączenie typu ajax i php, gdzie intervalem lacze sie co kilka sekund, i sprawdzam czy jest nowy id, jeśli tak to pobieram wiadomość nową? Jeśli raczej nie ma szans, to jak z kompatybilnością i obsługą jest z websocket? Słyszałem o nim, że o wiele łatwiej, jeśli chodzi o wydajność, ale serwis ma być też responsywny a więc i mobilne przeglądarki mogą różnie to interpretować. Jest sposób na obejście websocketa ( nie wiem z czym się go je itd, a czas mnie trochę goni... )
grzes999
Nie testowałem socketów nigdy na urządzeniach mobilnych; ale wydaje mi się, że nie powinno być z tym problemu, AJAX w tym przypadku nie ma sensu, jedyne służne rozwiażanie to użycie socketów, w google jest masa przykładów chata z wykorzystaniem socketów, możeszesz również skorzystać z tego przy pracy z socketami: WebSockets for PHP
bialko0019
hmm, tylko websocket dla mnie nie jest jeszcze prostym rozwiązaniem, no ale okey, jeśli nie ma innego wyjścia to trudno.. ;-P
Skie
Napisanie chatu w oparciu o WebSockety to dużo łatwiejszy sposób rozwiązania tego problemu niż bawienie się w polling lub long-polling w oparciu o AJAX. Również polecam Ci bibliotekę Ratchet, którą podlinkował @grzes999 - jest tam nawet Tutorial pisania chatu w oparciu o nią - czyli dokładnie to co potrzebujesz oraz rozwiązania typowych problemów, które możesz napotkać przy zdemonizowaniu procesu PHP.
Sama biblioteka w najniższych warstwach wspiera wiele różnych protokołów WebSocket używanych na przestrzeni lat przez przeglądarki, więć jeśli chodzi o komaptybilność to nie powinno być żadnych problemów.
Jeśli chodzi o samą wydajność to autor podaje mozliwość przetwrzania 1.000 wiadomości na sekundę, ale nie jest to twarda granica. Użytkownikom w grupie dyskusyjnej tej technologii udawało się uzyskać nawet 4 tys. wiadomości. Myślę, że korzystajać z PHP7 i dobrym serwerze dałoby się spokojnie uzyskać 10 tys.
W sieci jest dużo benchmarków porównujących Ratchet vs Nodejs, możesz tam znaleźć więcej informacji.
by_ikar
Stwórz coś z przykładów, zarówno w php jak i w node.js a potem użyj websocket-benchmark do przetestowania tego. Nigdy nie robiłem tego z użyciem php, zawsze bałem się ilości pamięci jaką php pochłonie..
pyro
Wsparcie websocketów przez przeglądarki: http://caniuse.com/#feat=websockets

Websockety > AJAX

Zamiast Ratcheta czy innych tego bibliotek lepiej użyć do tego node.js, jeśli masz taką możliwość
bialko0019
Witam ponownie. Dzieki za odpowiedzi. mam pytanie. Próbuję rozkminić websocket, ale nie do końca rozumiem idei i tym samym rozkminic,
Pobrałem klasę z https://github.com/Flynsarmy/PHPWebSocket-Chat , uruchomiłem na serwerze ( <?php exec('php server.php'); ?> ) i wszystko hula, tylko jak teraz zabić ten proces ? I czy muszę go raz na jakiś czas uruchamiać? Jak on obciąża serwer? ( nie localhost na xampp tylko już docelowym )

I moja najwieksza prośba o wyjaśnienie. Na jakiej zasadzie działa to, że user jest przydzielany tutaj i widzi wiadomości? Są w jakimś cache? Chcę zrobić tak, że ten chat jest dostępny tylko dla zalogowanych i tylko dla dwóch userów pomiędzy sobą, a wiadomości się zapisują w bazie? Gdzie moge szukać odpowiedzi? Różne IP dla różnych userów? A jak to rozkminić dla aktualnie zalogowanego do cms`a ?
Comandeer
Ta klasa nie ma być uruchamiana na serwerze, tylko uruchamiana jako serwer (PHP jako demon) - stąd polecono Ci node.js jako lepiej radzący sobie w takim przypadku i wręcz jakby stworzony dla websockets. + ma lepsze community od tych rzeczy (wystarczy wpisać w google socket.io i dostaniemy wszystko, co tylko chcemy o socketach na tej bibliotece, łącznie z tysiącem przykładów czatów wink.gif)

Tak na oko to tutaj po prostu każdy, kto się połączy, widzi wszystko. Jak potrzebujesz jakiejś autoryzacji userów, to trza by ją zrobić osobno i wówczas np wiązać połączenia z jednego browsera (w końcu każda karta = inne połączenie) z konkretną sesją usera.
bialko0019
czyli plik typu "server.php" jest w tle uruchamiany i z każdym żadaniem ( wysłanie , odbieranie ) jest wykonywany? Coś jak by ajaxowy chat, gdzie ten plik jest odświeżany cyklicznie?
grzes999
Cytat(bialko0019 @ 18.08.2015, 11:50:34 ) *
I moja najwieksza prośba o wyjaśnienie. Na jakiej zasadzie działa to, że user jest przydzielany tutaj i widzi wiadomości? Są w jakimś cache? Chcę zrobić tak, że ten chat jest dostępny tylko dla zalogowanych i tylko dla dwóch userów pomiędzy sobą, a wiadomości się zapisują w bazie? Gdzie moge szukać odpowiedzi? Różne IP dla różnych userów? A jak to rozkminić dla aktualnie zalogowanego do cms`a ?


Nie do końca rozumiem co chcesz osiągnąć, na chacie jednocześnie może przebywać wyłącznie dwie osoby? Czy chcesz zrobić coś w stylu chatów z supportem jest użytkownik z rolą admin i do niego podłączają się klienci?

Cytat(bialko0019 @ 18.08.2015, 11:50:34 ) *
Witam ponownie. Dzieki za odpowiedzi. mam pytanie. Próbuję rozkminić websocket, ale nie do końca rozumiem idei i tym samym rozkminic,
Pobrałem klasę z https://github.com/Flynsarmy/PHPWebSocket-Chat , uruchomiłem na serwerze ( <?php exec('php server.php'); ?> ) i wszystko hula, tylko jak teraz zabić ten proces ? I czy muszę go raz na jakiś czas uruchamiać? Jak on obciąża serwer? ( nie localhost na xampp tylko już docelowym )


Tak jak ci Comandeer napisał, uruchamiasz to jako serwer do tego typu rzeczy dobrze mieć jakiegoś zarządce, ja polecam supervisord

Cytat(bialko0019 @ 18.08.2015, 13:06:08 ) *
czyli plik typu "server.php" jest w tle uruchamiany i z każdym żadaniem ( wysłanie , odbieranie ) jest wykonywany? Coś jak by ajaxowy chat, gdzie ten plik jest odświeżany cyklicznie?


Ten plik jest twoim serwerem i nasłuchuje na podanym porcie czy jest jakieś połączenie bądź przyszła jakaś wiadomość, tak bardzo w skrócie i może mało technicznie; ale ma nadzieję że łapiesz o co chodzi
bialko0019
Chciałbym osiągnąć to, że w serwisie jest np. 100 userów. Każdy może kliknąć "wyslij wiadomość" do usera i może z nim porozmawiać. Taka wewnętrzna skrzynka wiadomości jeden do jednego ;-) Rozwiązałem to ajax`em, ale boję się, że np. przy 100 userach jednoczescie rozmawiających może serwer nie wytrzymać.. ;-) Myślę, że setka osób to byłby max na początek, chyba że ajax pojdzie?
grzes999
Cytat(bialko0019 @ 18.08.2015, 13:31:08 ) *
Chciałbym osiągnąć to, że w serwisie jest np. 100 userów. Każdy może kliknąć "wyslij wiadomość" do usera i może z nim porozmawiać. Taka wewnętrzna skrzynka wiadomości jeden do jednego ;-) Rozwiązałem to ajax`em, ale boję się, że np. przy 100 userach jednoczescie rozmawiających może serwer nie wytrzymać.. ;-) Myślę, że setka osób to byłby max na początek, chyba że ajax pojdzie?


Jeżeli rozwiązałeś to ajaxem to po prostu przenieś to na skrypt server.php i gotowe. Pomyśl, że masz 20 userów rozmawiających ze sobą to jest ok.1200 requestów na minutę + zapis, odczyt z bazy wiadomości; ale twój wybór
bialko0019
czyli myślisz, że serwer może nie dać rady przy ajax`owym requescie co 5sekund? ;-)

Kolega wyżej napisał "Ten plik jest twoim serwerem i nasłuchuje na podanym porcie czy jest jakieś połączenie bądź przyszła jakaś wiadomość" - czyli jaką funkcją mogę sprawdzić, czy ktoś coś wysłał z formularza?
!*!
https://github.com/Flynsarmy/PHPWebSocket-C...ster/server.php

Masz tam funkcje wsOnMessage która wysyła wiadomość do wszystkich prócz siebie, wykorzystuje to metodę wsSend z https://github.com/Flynsarmy/PHPWebSocket-C...HPWebSocket.php
Możesz to rozbić, i np po stronie JS (w zasadzie musisz), wysłać do serwera informacje że ma iść prywatna wiadomość "pm.ID.txt" wtedy serwer sam to rozkmini na wejściu i zamiast wysyłać do wszystkich wyśle do osoby o id do jakiej chciałeś, tylko musisz to napisać, ale to kwestia kilku linijek.
bialko0019
acha, ok dziękuję, będę to rozkminiać ;-)

Jako, że nie znam node.js w ogóle, to dużo czasu mi zejdzie na początek, by go załapać. Dowiedziałem się, że node`a trzeba zainstalować na serwerze, a niestety nie mam dostępu do dedyka, więc chyba ta opcja odpada. A więc jedynym rozwiązaniem jest zrobienie pliku typu "serwer.php" , który nasłuchiwał by czy dla danego użytkownika jest jakaś nowa wiadomość i wtedy ewentualnie wysyłał info do pliku, w którym się czyta wiadomości i je aktualizował tylko wtedy? Nie rozumiem jeszcze jednej rzeczy. Ten plik "serwer.php" żeby nasłuchiwał, to trzeba go uruchomić np. tak jak napisałęm, coś typu exec('php -q serwer.php'); a co właśnie potem, bo samo uruchomienie tego pliku wygasa? Kolega napisał, że najlepiej mieć "zarządce" ? Co to znaczy? Uruchomienie tego pliku czyli nasłuchiwanie portu po jakimś czasie wygasa, jak to zautomtyzować?

I tak się jeszcze dopytam - może znacie jakąś inną wydajniejszą opcję jak odpytywanie, ale mniej skomplikowaną i nie wymagającą dedyka jak node.js i socket.io ? Jeśli nie to może zrobić dłuższy interval dla odpytywania np. 8sekund w ajax...
Comandeer
Jak nie możesz tego odpalić w konsoli serwera, to nie ma sensu się w to bawić. Z poziomu strony to nie ma prawa działać.

Nie potrafisz zrozumieć, że ten plik PHP nie ma być serwowany z serwera, tylko sam służyć jako serwer. Ma działać podobnie do Apache'a - odpowiadać na żądania HTTP.

W takim wypadku zostaje comet aka long polling. Polecam poczytać w tym zakresie o Server-Sent Events
Skie
Widzę, że wolisz rozwiązanie PHP i odniosłeś sie w swoim poście do linka, który podałem , więc wytłumaczę Ci wszystko wg. działania Ratchet. Server.php to plik, który uruchamiasz na serwerze za pomocą komendy z konsoli serwera - np. przez putty.

  1. php server.php


Powinien on w nieskończonej pętli czekać na przychodzące wiadomości socketowe i w momencie otrzymia takiej wiadomości odpalać odpowiednią funkcję. Oczekiwanie, wyłączenie timeoutów PHP i całą warstwę odpowiedzialną za demonizację procesu PHP odpowiada moduł React/Loop, którego Ratchet używa, więc tutaj nie musisz się przejmować o tego typu problemami - tj. "wygasaniem" PHP.

Wspomniany serwer musi implementować 4 podstawowe funkcje - onStart, onStop, onMessage i onError - pierwsza uruchamiana jest w przypadku utworzenia nowego połączenia, druga w przypadku zamknięcia istniejącego, trzecia w przypadku otrzymania wiadomości i czwarta w przypadku błędu. Najważniejsza jest trzecia
  1. onMessage(ConnectionInterface $conn, MessageInterface $message)
. Funkcja ta ma podobne zadanie jak routing HTTP w przypadku frameworków MVC - odbierasz wiadomość $message od użytkownika $conn i następnie ją parsujesz i przkazujesz do odpowiedniego kontrolera w aplikacji. Odpowiedź generujesz za pomocą $conn->send(MessageInterface $response).

Dla porównania w MVC routing zrobiłbyś mniej więcej tak:
  1. Router::setController('/hello', new HelloWorldController());


Odpowiednik tego przy weboscket (ratchet) byłby taki:
  1. onMessage(ConnectionInterface $conn, MessageInterface $message) {
  2. switch ($message['get']) {
  3. case '/hello':
  4. $controller = new HelloWorldController();
  5. break;
  6.  
  7. /* ... */
  8. }
  9.  
  10. $conn->send(
  11. $controller->someAction($message)
  12. );
  13. }


Oczywiście możesz tutaj jaki syntax-sugar samemu zrobić by zapis byłby prostszy i np tworzyć nowe routingi za pomocą czeogś w stylu:
  1. Websocket::setController('/hello', new HelloWorldController());


To wszystko - łatwo, prosto i przyjemnie.

W tym momencie widzisz, że HTTP i WebSocket to osobne wejścia do Twojej aplikacji, ale jestes w stanie połączyć je obie z istniejącą już architekturą. Problemem jaki możesz napotkać to obiekt $Request, który może w tym przypadku nie istnieć wewnąrz aplikacji, która normalnie używa HTTP. Jeśli moduły z których chcesz skorzystać używają aktywnie Request i nie znajdziesz sposobu by zamockować go przy websocket, to możesz rozwiązać ten problem w taki sposób, by serwer.php po otrzymaniu wiadomości socket, wysyłał lokalnie zapytanie HTTP do Twojej aplikacji , czekał na odpowiedź i następnie odsyłał wiadomość przez socket. Postaraj sie jednak użyć tego w ostateczności.

W kwestii zarządcy, to problem jest taki - PHP domyślnie jest jednowątkowe - to oznacza, że jakikolwiek Fatal Error lub Unhandled Exception zamknie proces server.php , a co za tym idzie, Twoje webosckety przestaną działać. Rolą zarządcy jest monitorowanie danego procesu - tutaj server.php z poziomu systemu operacyjnego - po to, że jeślli zakończy on działanie, zarządca uruchomi go ponownie. Dzięki temu niebędziesz musiał się bać, że w przypadku wysypania się któregoś modułu Twoja aplikacja przestanie działac.

UWAGA:
Nie przepisuj kodu PHP, który podałem w tym poście słowo w słowo, gdyż jest to pseudokod pisany z pamięci, by dać Ci ogólne pojęcia jak to ustrukturyzować. Dokładne zapisy weź z manuala Ratchet.
grzes999
Mogę ci jeszcze podpowiedzieć, że w przypadku takich skryptów warto rejestrować wszelkie błędy oraz fatale register_shutdown_function
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.