Używasz komety z PHP?

82

Myślałem o wdrożeniu czatu w czasie rzeczywistym przy użyciu zaplecza PHP, ale natknąłem się na ten komentarz na stronie omawiającej kometę:

Rozumiem, że PHP jest okropnym językiem dla Comet, ponieważ Comet wymaga utrzymywania stałego połączenia otwartego z każdym klientem przeglądarki. Używając mod_php oznacza to wiązanie dziecka Apache w pełnym wymiarze czasu dla każdego klienta, który w ogóle nie jest skalowany. Ludzie, których znam, robiąc rzeczy z Comet, głównie używają Twisted Pythona, który jest zaprojektowany do obsługi setek lub tysięcy jednoczesnych połączeń.

Czy to prawda? A może jest to coś, co można skonfigurować?

ryeguy
źródło
4
możesz uruchomić php jako fastcgi ...
Itay Moav -Malimovka
4
Użyj nodeJS jako serwera, aby utrzymać połączenia klientów, gniazd internetowych w javascript, aby połączyć się z serwerem z przeglądarki. W tym sensie PHP może być uprzywilejowanym klientem, który będzie łączył się z nodejs, wysyłał dane usługowe, które będą w jakiś sposób traktowane po stronie klienta.
Artjom Kurapov
1
@ArtjomKurapov Możesz przekształcić PHP w serwer WWW, omijając w ten sposób metodę obsługi żądań Apache - pomyśl o tym jak o prawdziwym serwerze PHP, który zajmuje się tylko żądaniami komet .
Christian,
@Christian jeśli oznaczało wbudowany serwer WWW w PHP od 5,4 następnie jej tylko na rozwój i wykorzystanie go na produkcji jest zły pomysł
Artjom Kurapov
2
@ArtjomKurapov Nie, miałem na myśli napisanie prawdziwego serwera PHP, używając gniazd PHP do nasłuchiwania portu 80 i blokowania wejścia na czas nieokreślony - efektywnie jak działają serwery. Można to już zobaczyć w akcji w projektach takich jak phpwebsocket .
Christian,

Odpowiedzi:

61

Zgadzając się / rozszerzając to, co już zostało powiedziane, nie sądzę, że FastCGI rozwiąże problem.

Apache

Każde żądanie do Apache będzie używać jednego wątku roboczego do zakończenia żądania, co może być długim czasem w przypadku żądań COMET.

Ten artykuł o Ajaxian wspomina o używaniu COMET na Apache i że jest to trudne. Problem nie jest specyficzny dla PHP i dotyczy każdego modułu CGI zaplecza, którego możesz chcieć użyć na Apache.

Sugerowanym rozwiązaniem było użycie modułu MPM „zdarzenia”, który zmienia sposób wysyłania żądań do wątków roboczych.

Ten MPM próbuje rozwiązać problem z utrzymaniem aktywności w HTTP. Gdy klient zakończy pierwsze żądanie, może pozostawić połączenie otwarte i wysyłać kolejne żądania przy użyciu tego samego gniazda. Może to zaoszczędzić znacznych kosztów związanych z tworzeniem połączeń TCP. Jednak Apache tradycyjnie utrzymuje cały proces / wątek potomny w oczekiwaniu na dane od klienta, co ma swoje wady. Aby rozwiązać ten problem, ten MPM używa dedykowanego wątku do obsługi zarówno gniazd nasłuchujących, jak i wszystkich gniazd, które są w stanie utrzymywania aktywności.

Niestety to też nie działa, ponieważ „drzemie” dopiero po zakończeniu żądania, czekając na nowe żądanie od klienta.

PHP

Teraz, biorąc pod uwagę drugą stronę problemu, nawet jeśli rozwiążesz problem z zatrzymywaniem jednego wątku na żądanie komety, nadal będziesz potrzebować jednego wątku PHP na żądanie - dlatego FastCGI nie pomoże.

Potrzebujesz czegoś takiego jak Kontynuacje, które pozwolą na wznowienie żądań komety, gdy zostanie zaobserwowane zdarzenie, przez które zostały wyzwolone. AFAIK, to nie jest coś, co jest możliwe w PHP. Widziałem to tylko w Javie - zobacz serwer Apache Tomcat .

Edytować:

Jest tutaj artykuł o używaniu load balancera ( HAProxy ), który pozwala na uruchomienie zarówno serwera Apache, jak i serwera obsługującego kometę (np. Jetty, tomcat dla Java) na porcie 80 tego samego serwera.

Mike Houston
źródło
20
Zdaję sobie sprawę, że to nie do końca zapewnia rozwiązanie: /
Mike Houston
+1, ponieważ Apache / PHP nie są dobrymi opcjami do skalowania rozwiązania komety. Opcje dla użytkowników PHP to 1), jak wspomniałeś, szalone konfiguracje dodatkowych serwerów i serwerów proxy lub 2) korzystanie z rozwiązania SaaS i odciążanie komety za pośrednictwem czegoś takiego jak WebSync On-Demand.
jvenema
1
To jest złe w kilku aspektach. Jeśli ktoś chce opuścić metodę jednego wątku na użytkownika, można to łatwo osiągnąć, usuwając Apache jako pośrednika i pozwalając PHP obsłużyć te żądania. Oczywiście Apache działa lepiej w udostępnianiu treści, więc uruchomiłbym ten serwer PHP bez apache na subdomenie, która nie obsługuje żadnych treści.
Christian,
@MikeHouston A co powiesz na wypróbowanie komety z php w IIS.?
ravi404
@ravz, jest tu trochę rzeczy na temat IIS i komety: stackoverflow.com/questions/1898848/comet-programming-in-iis , ale podejrzewam, że moduł PHP fast-cgi ma takie same ograniczenia jak w przypadku apache. Wspomina tutaj o środowisku jednowątkowym: microsoft.com/web/platform/phponwindows.aspx - sam nie używam serwerów Windows, więc nie jestem pewien co do modelu wątków.
Mike Houston
14

Możesz użyć Nginx i JavaScript, aby zaimplementować system czatu oparty na Comet, który jest bardzo skalowalny przy niewielkim wykorzystaniu pamięci lub procesora.

Mam tutaj bardzo prosty przykład, od którego możesz zacząć. Obejmuje kompilację Nginx z modułem NHPM i zawiera kod dla prostych ról wydawcy / subskrybenta w jQuery, PHP i Bash.

http://blog.jamieisaacs.com/2010/08/27/comet-with-nginx-and-jquery/

Jamie
źródło
10

PHP

Znalazłem zabawne małe screencasty wyjaśniające prostą kometę. Na marginesie, naprawdę myślę, że to zabije twój serwer przy każdym rzeczywistym obciążeniu. Mając tylko kilku użytkowników, powiedziałbym, że warto wybrać to rozwiązanie. To rozwiązanie jest naprawdę proste do wdrożenia (screencast zajmuje tylko 5 minut Twojego czasu :)). Ale jak mówiłem wcześniej, nie sądzę, żeby to było dobre dla wielu jednoczesnych użytkowników (chyba powinieneś to porównać;)), ponieważ:

  1. Używa wejścia / wyjścia pliku, które jest znacznie wolniejsze niż pobieranie danych z pamięci. Jak na przykład funkcje filemtime(),
  2. Po drugie, ale nie sądzę najmniej, że PHP nie ma przyzwoitego modelu wątków. PHP i tak nie zostało do tego zaprojektowane z powodu modelu share none . Na slajdach jest napisane, że „Udostępnione dane są wypychane do warstwy przechowywania danych”, jak na przykład MySQL.

Alternatywy

Naprawdę uważam, że powinieneś wypróbować alternatywy, jeśli chcesz przeprowadzić badanie komet / długich sondaży. Możesz używać wielu języków, na przykład:

  • Java / JVM: kontynuacje Jetty .
  • Python: Dustin breja .
  • Erlang: Popularny język dla komet / itp.
  • Lua, Ruby, C, Perl żeby wymienić tylko kilka.

Samo wykonanie prostego wyszukiwania w Google pokaże ci wiele alternatyw, także PHP (które myślę, że przy każdym dużym obciążeniu zabije twój serwer).

Alfred
źródło
6

Możesz także spróbować https://github.com/reactphp/react

React to niskopoziomowa biblioteka do programowania sterowanego zdarzeniami w PHP. Jego rdzeniem jest pętla zdarzeń, na szczycie której zapewnia narzędzia niskiego poziomu, takie jak: abstrakcja strumieni, asynchroniczny przelicznik dns, klient / serwer sieciowy, klient / serwer http, interakcja z procesami. Biblioteki innych firm mogą używać tych składników do tworzenia asynchronicznych klientów / serwerów sieciowych i nie tylko.

Pętla zdarzeń jest oparta na wzorze reaktora (stąd nazwa) i silnie inspirowana bibliotekami, takimi jak EventMachine (Ruby), Twisted (Python) i Node.js (V8).

Wstępny przykład przedstawia prosty serwer HTTP nasłuchujący na porcie 1337:

<?php

$i = 0;

$app = function ($request, $response) use (&$i) {
    $i++;

    $text = "This is request number $i.\n";
    $headers = array('Content-Type' => 'text/plain');

    $response->writeHead(200, $headers);
    $response->end($text);
};

$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server($loop);
$http = new React\Http\Server($socket);

$http->on('request', $app);

$socket->listen(1337);
$loop->run();
Gordon
źródło
4

Mam podobny problem. Jedną z interesujących opcji jest użycie istniejącego serwera Comet, takiego jak cometd-java lub cometd-python, jako głównego centrum wiadomości. Twój kod PHP jest wtedy tylko klientem serwera Comet - może wysyłać lub czytać wiadomości z kanałów, tak jak inni klienci.

Link do interesującego fragmentu kodu: http://morglog.org/?p=22=1, który implementuje część tej metody (chociaż są też fragmenty kodu debugowania).

Evan P.
źródło
3

Obecnie wdrażam skalowalny serwer PHP Comet przy użyciu funkcji gniazd. Nazywa się „phet” ([ph] p com [et])

Strona projektu: http://github.com/Tim-Smart/phet

Bezpłatnie za darmo dołączyć do rozwoju. Obecnie udało mi się wykonać większość logiki serwera, wystarczy dokończyć czynności po stronie klienta.

EDYCJA: Ostatnio dodane możliwości 'wielowątkowości' przy użyciu pcntl_forkmetody :)

Tim
źródło
Nie ma łatwo dostępnych przykładów użycia tej biblioteki.
ftrotter
3

Będziesz miał trudności z implementacją komety w PHP, tylko z powodu jej wrodzonej jednowątkowości.

Wypróbuj Websync On-Demand - usługa ta pozwala na integrację PHP poprzez publikowanie po stronie serwera, odciążając wiele jednoczesnych połączeń i pozwala błyskawicznie utworzyć aplikację do czatu w czasie rzeczywistym.

jvenema
źródło
1

Będziesz musiał stworzyć własny serwer w PHP. Używanie Apache / mod_php lub nawet fastcgi w ogóle nie skaluje się. Kilka lat, ale możesz zacząć:

PHP-Comet-Server: http://sourceforge.net/projects/comet/

sroussey
źródło
0

Myślę, że jest to bardziej problem, że posiadanie wielu wątków Apache działających przez cały czas jest problemem. Będzie to istniało z każdym językiem, jeśli działa przez apache w taki sam sposób, jak PHP (zwykle).

benlumley
źródło
1
Myślę, że chodzi o to, że zwykle uruchamiasz php w procesie na żądanie, a nie w wątku na żądanie.
troelskn