Kometen mit PHP verwenden?

82

Ich habe überlegt, Echtzeit-Chat mit einem PHP-Backend zu implementieren, bin aber auf diesen Kommentar auf einer Website gestoßen, auf der es um Kometen geht:

Mein Verständnis ist, dass PHP eine schreckliche Sprache für Comet ist, da Comet erfordert, dass Sie eine dauerhafte Verbindung zu jedem Browser-Client aufrechterhalten. Bei Verwendung von mod_php bedeutet dies, dass für jeden Client, der überhaupt nicht skaliert, ein Apache-Kind in Vollzeit gebunden wird. Die Leute, die ich kenne, die Comet-Sachen machen, verwenden meistens Twisted Python, das für Hunderte oder Tausende gleichzeitiger Verbindungen ausgelegt ist.

Ist das wahr? Oder kann es konfiguriert werden?

Ryeguy
quelle
4
Sie können PHP als Fastcgi ausführen ...
Itay Moav -Malimovka
4
Verwenden Sie nodeJS als Server, um Clientverbindungen aufrechtzuerhalten, Websockets in Javascript, um vom Browser aus eine Verbindung zum Server herzustellen. PHP in diesem Sinne kann ein privilegierter Client sein, der eine Verbindung zu nodejs herstellt und einige Servicedaten pusht, die auf der Clientseite irgendwie behandelt werden.
Artjom Kurapov
1
@ArtjomKurapov Sie können PHP zu einem Webserver machen und so die Apache-Methode zur Verarbeitung von Anforderungen umgehen. Stellen Sie sich das wie einen echten PHP-Server vor, der sich nur um Kometenanforderungen kümmert .
Christian
@Christian, wenn Sie seit 5.4 eingebauten PHP-Webserver gemeint haben, dann ist es nur für die Entwicklung und die Verwendung in der Produktion eine schlechte Idee
Artjom Kurapov
2
@ArtjomKurapov Nein, ich wollte einen echten PHP-Server schreiben, indem ich PHP-Sockets verwendete, um Port 80 abzuhören und Eingaben auf unbestimmte Zeit zu blockieren - effektiv, wie Server funktionieren. Dies ist bereits in Projekten wie phpwebsocket in Aktion zu sehen .
Christian

Antworten:

61

Ich stimme nicht zu, dass FastCGI das Problem lösen wird.

Apache

Jede Anforderung an Apache verwendet einen Arbeitsthread, bis die Anforderung abgeschlossen ist. Dies kann für COMET-Anforderungen eine lange Zeit in Anspruch nehmen.

In diesem Artikel über Ajaxian wird erwähnt, dass COMET unter Apache verwendet wird und dass dies schwierig ist. Das Problem ist nicht PHP-spezifisch und gilt für alle Back-End-CGI-Module, die Sie möglicherweise für Apache verwenden möchten.

Die vorgeschlagene Lösung bestand darin, das MPM-Modul "Ereignis" zu verwenden, mit dem die Art und Weise geändert wird, in der Anforderungen an Arbeitsthreads gesendet werden.

Dieses MPM versucht, das Problem "Keep Alive" in HTTP zu beheben. Nachdem ein Client die erste Anforderung abgeschlossen hat, kann der Client die Verbindung offen halten und weitere Anforderungen über denselben Socket senden. Dies kann erheblichen Aufwand beim Erstellen von TCP-Verbindungen sparen. Apache lässt jedoch traditionell einen gesamten untergeordneten Prozess / Thread auf Daten vom Client warten, was seine eigenen Nachteile mit sich bringt. Um dieses Problem zu lösen, verwendet dieses MPM einen dedizierten Thread, um sowohl die Listening-Sockets als auch alle Sockets zu verarbeiten, die sich in einem Keep Alive-Status befinden.

Leider funktioniert das auch nicht, da es erst nach Abschluss einer Anfrage "schlummert" und auf eine neue Anfrage vom Client wartet.

PHP

Wenn Sie nun die andere Seite des Problems betrachten, benötigen Sie auch dann einen PHP-Thread pro Anforderung, wenn Sie das Problem mit dem Halten eines Threads pro Kometenanforderung beheben. Aus diesem Grund hilft FastCGI nicht weiter.

Sie benötigen so etwas wie Fortsetzungen, mit denen die Kometenanforderungen wieder aufgenommen werden können, wenn das Ereignis beobachtet wird, durch das sie ausgelöst werden. AFAIK, das ist in PHP nicht möglich. Ich habe es nur in Java gesehen - siehe den Apache Tomcat-Server .

Bearbeiten:

Es gibt hier einen Artikel über die Verwendung eines Load Balancers ( HAProxy ), mit dem Sie sowohl einen Apache-Server als auch einen Kometen-fähigen Server (z. B. Jetty, Tomcat für Java) auf Port 80 desselben Servers ausführen können.

Mike Houston
quelle
20
Mir ist klar, dass dies keine Lösung darstellt: /
Mike Houston
+1, da Apache / PHP keine guten Optionen zum Skalieren einer Kometenlösung sind. Optionen für PHP-Benutzer sind 1) wie bereits erwähnt, verrückte Konfigurationen zusätzlicher Server und Proxys oder 2) die Verwendung einer SaaS-Lösung und das Auslagern des Kometenmaterials über WebSync On-Demand.
Jvenema
1
Dies ist in mehrfacher Hinsicht falsch. Wenn Sie die Ein-Thread-pro-Benutzer-Methode verlassen möchten, können Sie dies leicht erreichen, indem Sie Apache als Vermittler entfernen und PHP diese Anforderungen bearbeiten lassen. Natürlich funktioniert Apache besser beim Bereitstellen von Inhalten, daher würde ich diesen apachefreien PHP-Server auf einer Subdomain ausführen, die keinen Inhalt bereitstellt.
Christian
@ MikeHouston Was ist mit einem Kometen mit PHP in IIS?
Ravi404
@ravz, hier gibt es einige Dinge über IIS und Kometen: stackoverflow.com/questions/1898848/comet-programming-in-iis , aber ich vermute, dass das Fast-CGI-PHP-Modul die gleichen Einschränkungen aufweist wie Apache. Hier wird eine einzelne Thread-Umgebung erwähnt: microsoft.com/web/platform/phponwindows.aspx - Ich verwende selbst keine Windows-Server, daher bin ich mir über das Threading-Modell nicht sicher.
Mike Houston
14

Sie können Nginx und JavaScript verwenden, um ein Comet-basiertes Chat-System zu implementieren, das mit wenig Speicher- oder CPU-Auslastung sehr skalierbar ist.

Ich habe hier ein sehr einfaches Beispiel, mit dem Sie beginnen können. Es behandelt das Kompilieren von Nginx mit dem NHPM-Modul und enthält Code für einfache Publisher- / Subscriber-Rollen in jQuery, PHP und Bash.

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

Jamie
quelle
10

PHP

Ich fand diese lustigen kleinen Screencasts , die einfache Kometen erklären. Als Randnotiz denke ich wirklich, dass dies Ihren Server bei jeder realen Last töten wird. Wenn ich nur ein paar Benutzer habe, würde ich sagen, dass ich mich nur für diese Lösung entscheide. Diese Lösung ist wirklich einfach zu implementieren (Screencasts dauern nur 5 Minuten :)). Aber wie ich bereits sagte, denke ich nicht, dass es für viele gleichzeitige Benutzer gut ist (ich denke, Sie sollten es vergleichen;)), weil:

  1. Es werden Datei-E / A verwendet, die viel langsamer sind als nur das Abrufen von Daten aus dem Speicher. Wie zum Beispiel die Funktionen filemtime(),
  2. Zweitens, aber ich denke nicht, dass PHP kein anständiges Thread-Modell hat. PHP wurde wegen des Share-Nothing-Modells sowieso nicht dafür entwickelt . Wie auf den Folien steht "Gemeinsame Daten werden in die Datenspeicherschicht verschoben", wie zum Beispiel MySQL.

Alternativen

Ich denke wirklich, Sie sollten die Alternativen ausprobieren, wenn Sie Kometen- / Langabfragen durchführen möchten. Sie könnten viele Sprachen verwenden, wie zum Beispiel:

  • Java / JVM: Fortsetzung der Anlegestelle .
  • Python: Dustins Schwappen .
  • Erlang: Beliebte Sprache für Kometen / etc.
  • Lua, Ruby, C, Perl, um nur einige zu nennen.

Nur eine einfache Google-Suche durchzuführen, zeigt Ihnen viele Alternativen auch PHP (was meiner Meinung nach bei jeder großen Last Ihren Server töten wird).

Alfred
quelle
7

mod_php ist nicht die einzige Möglichkeit, PHP zu verwenden. Sie können fastcgi verwenden. PHP muss mit kompiliert werden --enable-fastcgi.

PHP als FastCGI: http://www.fastcgi.com/drupal/node/5?q=node/10

vartec
quelle
6

Sie können auch https://github.com/reactphp/react ausprobieren

React ist eine Bibliothek auf niedriger Ebene für die ereignisgesteuerte Programmierung in PHP. Im Mittelpunkt steht eine Ereignisschleife, über die Dienstprogramme auf niedriger Ebene bereitgestellt werden, z. B.: Stream-Abstraktion, asynchroner DNS-Resolver, Netzwerk-Client / Server, http-Client / Server, Interaktion mit Prozessen. Bibliotheken von Drittanbietern können diese Komponenten verwenden, um asynchrone Netzwerkclients / -server und mehr zu erstellen.

Die Ereignisschleife basiert auf dem Reaktormuster (daher der Name) und ist stark von Bibliotheken wie EventMachine (Ruby), Twisted (Python) und Node.js (V8) inspiriert.

Das Einführungsbeispiel zeigt einen einfachen HTTP-Server, der Port 1337 überwacht:

<?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
quelle
4

Ich habe ein ähnliches Problem. Eine Option, die ich interessant finde, ist die Verwendung eines vorhandenen Comet-Servers wie cometd-java oder cometd-python als Kernnachrichten-Hub. Ihr PHP-Code ist dann nur ein Client für den Comet-Server - er kann wie andere Clients Nachrichten von Kanälen posten oder lesen.

Hier ist ein interessantes Code-Snippet verlinkt: http://morglog.org/?p=22=1 , das einen Teil dieser Methode implementiert (obwohl auch einige Teile des Debug-Codes verteilt sind).

Evan P.
quelle
3

Ich implementiere derzeit einen skalierbaren PHP Comet-Server mit Socket-Funktionen. Es heißt "Phet" ([ph] p com [et])

Projektseite: http://github.com/Tim-Smart/phet

Kostenlos kostenlos an der Entwicklung teilnehmen. Ich habe es derzeit geschafft, den größten Teil der Serverlogik zu erledigen. Ich muss nur die clientseitigen Aufgaben erledigen.

BEARBEITEN: Kürzlich wurden 'Multithreading'-Funktionen mit der pcntl_forkMethode hinzugefügt :)

Tim
quelle
Es gibt keine verfügbaren Beispiele für die Verwendung dieser Bibliothek.
ftrotter
3

Es wird Ihnen schwer fallen, Kometen in PHP zu implementieren, nur weil es Single-Threaded ist.

Check out websync On-Demand - der Service kann Sie PHP über serverseitige Publishing integrieren, die schweren gleichzeitige Verbindung Sachen Offloading, und lassen Sie eine Echtzeit - Chat - Anwendung in kürzester Zeit erstellen.

jvenema
quelle
1

Sie müssen Ihren eigenen Server in PHP erstellen. Die Verwendung von Apache / mod_php oder sogar fastcgi wird überhaupt nicht skaliert. Ein paar Jahre alt, aber Sie können loslegen:

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

Sroussey
quelle
0

Ich denke, dies ist eher ein Problem, bei dem es ein Problem ist, wenn viele Apache-Threads ständig ausgeführt werden. Das wird mit jeder Sprache existieren, wenn es über Apache genauso funktioniert wie PHP (normalerweise).

Benlumley
quelle
1
Ich denke, der Punkt ist, dass Sie normalerweise PHP in einem Prozess pro Anfrage ausführen, anstatt einen Thread pro Anfrage.
Troelskn