¿Usando cometa con PHP?

82

Estaba pensando en implementar el chat en tiempo real usando un backend PHP, pero encontré este comentario en un sitio que habla de cometa:

Tengo entendido que PHP es un lenguaje terrible para Comet, porque Comet requiere que mantenga abierta una conexión persistente para cada cliente de navegador. Usar mod_php significa ocupar un niño Apache a tiempo completo para cada cliente que no escala en absoluto. Las personas que conozco que hacen cosas de Comet utilizan principalmente Twisted Python, que está diseñado para manejar cientos o miles de conexiones simultáneas.

¿Es esto cierto? ¿O es algo que se puede configurar?

centeno
fuente
4
puede ejecutar php como fastcgi ...
Itay Moav -Malimovka
4
Utilice nodeJS como servidor para mantener las conexiones del cliente, websockets en javascript para conectarse al servidor desde el navegador. PHP en este sentido puede ser un cliente privilegiado que se conectará a nodejs, enviará algunos datos de servicio que serán tratados de alguna manera en el lado del cliente.
Artjom Kurapov
1
@ArtjomKurapov Puede convertir PHP en un servidor web evitando así el método de manejo de solicitudes de Apache; considérelo como un servidor PHP real que se ocupa únicamente de las solicitudes de cometa .
Christian
@Christian si te refieres al servidor web php incorporado desde 5.4, entonces es solo para desarrollo y usarlo en producción es una mala idea
Artjom Kurapov
2
@ArtjomKurapov No, me refería a escribir un servidor PHP real, usando sockets PHP para escuchar el puerto 80 y bloquear la entrada indefinidamente, cómo funcionan los servidores de manera efectiva. Esto ya se puede ver en acción en proyectos como phpwebsocket .
Christian

Respuestas:

61

Al estar de acuerdo / expandir lo que ya se ha dicho, no creo que FastCGI resuelva el problema.

apache

Cada solicitud en Apache utilizará un hilo de trabajo hasta que se complete la solicitud, lo que puede ser mucho tiempo para las solicitudes COMET.

Este artículo sobre Ajaxian menciona el uso de COMET en Apache y que es difícil. El problema no es específico de PHP y se aplica a cualquier módulo CGI de back-end que desee utilizar en Apache.

La solución sugerida fue utilizar el módulo MPM de 'evento' que cambia la forma en que se envían las solicitudes a los hilos de trabajo.

Este MPM intenta solucionar el "problema de mantener vivo" en HTTP. Una vez que un cliente completa la primera solicitud, el cliente puede mantener la conexión abierta y enviar más solicitudes utilizando el mismo socket. Esto puede ahorrar una sobrecarga significativa en la creación de conexiones TCP. Sin embargo, Apache tradicionalmente mantiene un proceso / subproceso hijo completo esperando datos del cliente, lo que trae sus propias desventajas. Para resolver este problema, este MPM utiliza un hilo dedicado para manejar tanto los enchufes de escucha como todos los enchufes que están en un estado Keep Alive.

Desafortunadamente, eso tampoco funciona, porque solo se 'pospondrá' después de que se complete una solicitud, esperando una nueva solicitud del cliente.

PHP

Ahora, considerando el otro lado del problema, incluso si resuelve el problema de mantener un hilo por solicitud de cometa, aún necesitará un hilo de PHP por solicitud; esta es la razón por la que FastCGI no ayudará.

Necesita algo como Continuaciones que permitan que las solicitudes de cometas se reanuden cuando se observe el evento que los desencadenó. AFAIK, esto no es algo que sea posible en PHP. Solo lo he visto en Java: consulte el servidor Apache Tomcat .

Editar:

Aquí hay un artículo sobre el uso de un equilibrador de carga ( HAProxy ) para permitirle ejecutar tanto un servidor apache como un servidor habilitado para cometas (por ejemplo, jetty, tomcat para Java) en el puerto 80 del mismo servidor.

Mike Houston
fuente
20
Me doy cuenta de que esto no proporciona exactamente una solución: /
Mike Houston
+1 porque Apache / PHP no son buenas opciones para escalar una solución cometa. Las opciones para los usuarios de PHP son 1) como mencionaste, configuraciones locas de servidores y proxies adicionales o 2) usar una solución SaaS y descargar las cosas del cometa mediante algo como WebSync On-Demand.
jvenema
1
Esto está mal en varios aspectos. Si uno quiere dejar el método de un hilo por usuario, se puede lograr fácilmente eliminando Apache como intermediario y dejando que PHP maneje estas solicitudes. Por supuesto, Apache funciona mejor en el servicio de contenido, por lo que ejecutaría este servidor PHP sin apache en un subdominio que no ofrezca ningún contenido.
Christian
@MikeHouston ¿Qué hay de probar Comet con php en IIS?
ravi404
@ravz, hay algunas cosas aquí sobre IIS y comet: stackoverflow.com/questions/1898848/comet-programming-in-iis , pero sospecho que el módulo PHP fast-cgi tiene las mismas limitaciones que con apache. Aquí menciona un entorno de un solo subproceso: microsoft.com/web/platform/phponwindows.aspx - Yo mismo no uso servidores Windows, así que no estoy seguro del modelo de subprocesamiento.
Mike Houston
14

Puede usar Nginx y JavaScript para implementar un sistema de chat basado en Comet que es muy escalable con poca memoria o uso de CPU.

Aquí tengo un ejemplo muy simple que puede ayudarlo a comenzar. Cubre la compilación de Nginx con el módulo NHPM e incluye código para roles simples de editor / suscriptor en jQuery, PHP y Bash.

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

Jamie
fuente
10

PHP

Encontré estos pequeños screencasts divertidos que explican un cometa simple. Como nota al margen, realmente creo que esto matará su servidor con cualquier carga real. Cuando solo tenga un par de usuarios, diría que elija esta solución. Esta solución es realmente simple de implementar (los screencasts solo toman 5 minutos de su tiempo :)). Pero como estaba diciendo anteriormente, no creo que sea bueno para muchos usuarios concurrentes (supongo que debería compararlo;)) porque:

  1. Utiliza E / S de archivos, que es mucho más lento que simplemente obtener datos de la memoria. Como por ejemplo las funciones filemtime(),
  2. En segundo lugar, pero no creo que al menos PHP no tenga un modelo de hilo decente. PHP no fue diseñado para esto de todos modos debido al modelo de compartir nada . Como dice la diapositiva, "los datos compartidos se envían a la capa de almacenamiento de datos", como por ejemplo MySQL.

Alternativas

Realmente creo que deberías probar las alternativas si quieres hacer una encuesta cometa / larga. Podrías usar muchos idiomas como, por ejemplo:

  • Java / JVM: continuaciones de Jetty .
  • Python: el chapoteo de Dustin .
  • Erlang: lenguaje popular para cometa / etc.
  • Lua, Ruby, C, Perl, solo por nombrar algunos.

Simplemente realizando una simple búsqueda en Google, le mostrará muchas alternativas también PHP (que creo que en cualquier gran carga matará su servidor).

Alfredo
fuente
6

También puede probar https://github.com/reactphp/react

React es una biblioteca de bajo nivel para programación impulsada por eventos en PHP. En su núcleo hay un bucle de eventos, además del cual proporciona utilidades de bajo nivel, tales como: abstracción de flujos, resolución dns asíncrona, cliente / servidor de red, cliente / servidor http, interacción con procesos. Las bibliotecas de terceros pueden usar estos componentes para crear clientes / servidores de red asíncronos y más.

El bucle de eventos se basa en el patrón de reactor (de ahí el nombre) y está fuertemente inspirado en bibliotecas como EventMachine (Ruby), Twisted (Python) y Node.js (V8).

El ejemplo introductorio muestra un servidor HTTP simple que escucha en el puerto 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
fuente
4

Tengo un problema similar. Una opción que encuentro interesante es utilizar un servidor Comet existente, como cometd-java o cometd-python, como centro de mensajes principal. Su código PHP es solo un cliente para el servidor Comet: puede publicar o leer mensajes de canales, al igual que otros clientes.

Hay un fragmento de código interesante vinculado aquí: http://morglog.org/?p=22=1 que implementa parte de este método (aunque también hay fragmentos de código de depuración repartidos).

Evan P.
fuente
3

Actualmente estoy implementando un servidor PHP Comet escalable usando funciones de socket. Se llama 'phet' ([ph] p com [et])

Página del proyecto: http://github.com/Tim-Smart/phet

Gratis gratis para participar en el desarrollo. Actualmente he logrado completar la mayor parte de la lógica del servidor, solo necesito terminar con las cosas del lado del cliente.

EDITAR: Capacidades de 'multiproceso' recientemente agregadas usando el pcntl_forkmétodo :)

Tim
fuente
No hay ejemplos disponibles sobre cómo utilizar esta biblioteca.
ftrotter
3

Te resultará difícil implementar cometa en PHP, solo por su carácter inherente de un solo subproceso.

Eche un vistazo a Websync On-Demand : el servicio le permite integrar PHP a través de la publicación del lado del servidor, descargando las pesadas conexiones concurrentes y le permitirá crear una aplicación de chat en tiempo real en poco tiempo.

jvenema
fuente
1

Tendrá que crear su propio servidor en PHP. El uso de Apache / mod_php o incluso fastcgi no se escalará en absoluto. Tiene algunos años, pero puede ayudarlo a comenzar:

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

sroussey
fuente
0

Creo que esto es más un problema que tener muchos hilos apache ejecutándose todo el tiempo es un problema. Eso existirá con cualquier lenguaje si funciona a través de Apache de la misma manera que PHP (generalmente).

Benlumley
fuente
1
Creo que el punto es que normalmente ejecutas php en un proceso por solicitud, en lugar de un hilo por solicitud.
troelskn