2011-12-26 8 views
5

Js:bucle infinitivo de PHP o jQuery setInterval?

<script> 
function cometConnect(){ 
    $.ajax({ 
      cache:false, 
      type:"post", 
      data:'ts='+1, 
      url: 'Controller/chatting', 
      async: true, 
      success: function (arr1) { 
       $(".page-header").append(arr1); 
      }, 
      complete:function(){ 
      cometConnect(true); 
      nerr=false; 
      }, 
      dataType: "text" 
     }); 
} 
cometConnect(); 
</script> 

PHP:

public function chatting() 
{ 
    while(true) 
    { 
     if(memcache_get(new_message)) 
      return new_message; 
     sleep(0.5); 
    } 
} 

¿Es esta una solución mejor que la configuración setInterval que conecta con el método PHP que devuelve el mensaje si hay cualquier cada 1 segundo (1 seg aumenta +0,25 cada 5 segundos, digamos)?

Si utilicé la primera solución, probablemente podría utilizar sleep (0.5), me daría mensajes instantáneamente, porque php loop es barato, ¿no?

Entonces, ¿qué solución es mejor (más importante aún, que requiere menos recursos?). Porque van a haber cientos de chats como este.

Además, ¿puede la primera solución causar problemas? Digamos que volvería a cargar una página o dejaría de ejecutar cada 30 segundos para no obtener 502 Bad Gateway.

EDIT: Creo que la segunda solución es mejor, por lo que voy a volver a implementar mi sitio, pero tengo curiosidad si esto puede causar problemas al usuario o no? ¿Puede pasar algo inesperado? El primer problema que noté es que no puede ir a otra página hasta que haya al menos un mensaje nuevo.

Respuesta

9

Un chat es una comunicación de uno a muchos, mientras que cada uno de los muchos puede enviar mensajes y recibirá mensajes de todos los demás.

Estas dos acciones (envío, recepción) ocurren continuamente. Así que esto parece un ciclo sin fin, mientras que el usuario puede ingresar (unirse al chat) y salir (abandonar el chat).

  1. entrar
  2. enviar mensaje
  3. recibir el mensaje
  4. salida

Así que el bucle se parece a esto (pseudo-código) en el lado del cliente:

while (userInChat) 
{ 
    if (userEnteredMessages) 
    { 
     userSendMessages(userEnteredMessages) 
    } 
    if (chatNewMessages) 
    { 
     displayMessages(chatNewMessages) 
    } 
} 

Como ya nota en su pregunta, el problema es implementar tal tipo de chat para un sitio web.

Para implementar dicho "bucle" para un sitio web, ante todo se enfrenta a la situación de que no desea tener un bucle real aquí. Mientras el usuario esté en el chat, se ejecutará, se ejecutará y se ejecutará. Entonces, quiere distribuir la ejecución del ciclo a lo largo del tiempo.

Para ello, se puede convertir en una colección de funciones de eventos:

ChatClient 
{ 
    function onEnter() 
    { 
    } 
    function onUserInput(messages) 
    { 
     sendMessages = send(messages) 

     display(sendMessages) 
    } 
    function onReceive(messages) 
    { 
     display(messages) 
    } 
    function onExit() 
    { 
    } 
} 

Ahora es posible activar eventos en lugar de tener un bucle. Solo queda la implementación para desencadenar estos eventos a lo largo del tiempo, pero por el momento esto no es realmente interesante porque dependería de cómo se implementa realmente el intercambio de datos de chat.

Siempre hay un punto remoto donde un cliente de chat está (de alguna manera) conectado para enviar sus propios mensajes y recibir nuevos mensajes de.

Esto es una especie de transmisión de mensajes de chat. De nuevo, esto parece un bucle, pero de hecho es una secuencia. Al igual que en el bucle de clientes de chat, en algún momento se engancha a la transmisión y enviará entrada (escritura) y recibirá salida (lectura) de esa transmisión.

Esto ya es visible en el pseudocódigo ChatClient anterior, hay un evento cuando el usuario ingresa uno o varios mensajes que luego serán enviados (escritos). Y los mensajes de lectura estarán disponibles en la función de evento onReceive.

Como la transmisión de datos está en orden, es necesario que haya orden. Como todo esto está basado en eventos y hay varios clientes disponibles, esto requiere un manejo dedicado. Como el orden es relativo, solo funcionará en su contexto. El contexto podría ser el momento (un mensaje llegó antes de otro mensaje), pero si el cliente de chat tiene otro reloj como el servidor u otro cliente, no podemos usar el reloj existente como fuente de tiempo para el orden de los mensajes, ya que normalmente difiere entre computadoras en una WAN.

En su lugar, puede crear su propio tiempo para alinear todos los mensajes. Con un tiempo compartido en todos los clientes y servidores, se puede implementar una secuencia ordenada. Esto se puede hacer fácilmente simplemente numerando los mensajes en un lugar central. Afortunadamente, su chat tiene un lugar central, el servidor.

La secuencia de mensajes comienza con el primer mensaje y finaliza con el último. Entonces, lo que simplemente debe hacer es dar el primer mensaje al número 1 y luego cada nuevo mensaje obtendrá el siguiente número más alto. Vamos a llamarlo ID del mensaje.

Por lo tanto, independientemente de la tecnología de servidor que vaya a utilizar, el chat sabe qué tipo de mensajes: mensajes con una ID y mensajes sin ID.Esto también representa el estado de un mensaje: ya sea no parte o parte de la transmisión.

Los mensajes asociados a la transmisión no son los que el usuario ya ha ingresado pero que aún no se han enviado al servidor. Mientras que el servidor recibe los mensajes de "libres", puede ponerlos en la corriente mediante la asignación de la ID:

function onUserInput(messages) 
    { 
     sendMessages = send(messages) 

     display(sendMessages) 
    } 

Como este ejemplo muestra pseudo código, esto es lo que está pasando aquí. El evento onUserInput recibe mensajes que aún no forman parte de la transmisión. La rutina sendMessages devolverá su representación transmitida, que luego se mostrará.

La rutina de visualización luego puede mostrar los mensajes en su orden de transmisión.

Por lo tanto, independientemente de cómo se implemente la comunicación entre el cliente y el servidor, con esa estructura, puede manejar un sistema de chat basado en mensajes y desvincularlo de las tecnologías subyacentes.

Lo único que debe hacer el servidor es tomar los mensajes, dar a cada mensaje una ID y devolver estos ID. La asignación de la ID normalmente se hace cuando el servidor almacena los mensajes en su base de datos. Una buena base de datos se ocupa de numerar correctamente los mensajes, por lo que no hay mucho que hacer.

La otra interacción es leer mensajes nuevos del servidor. Para hacer esto a través de la red de manera efectiva, el cliente le dice al servidor de qué mensaje le gusta leer. El servidor pasará los mensajes desde ese momento (ID) al cliente.

Como muestra esto, desde el ciclo "interminable" al principio, ahora se ha convertido en un sistema basado en eventos con llamadas remotas. Como las llamadas remotas son costosas, es mejor hacer que puedan transferir mucha información con una conexión. Parte de eso ya está en el pseudo código, ya que es posible enviar uno o varios mensajes al servidor y recibir cero o más mensajes del servidor a la vez.

La implementación ideal sería tener una conexión con el servidor que permita leer y escribir mensajes en dúplex completo. Sin embargo, aún no existe esa tecnología en javascript. Estas cosas están en desarrollo con Websockets y APIs de Webstream y similares, pero por el momento vamos a ver las cosas simples y ver lo que tenemos: solicitudes HTTP sin estado, algunas PHP en el servidor y una base de datos MySQL.

La secuencia de mensajes se puede representar en una tabla de base de datos que tiene una clave única de incremento automático para el ID y otros campos para almacenar el mensaje.

El script de transacción de escritura simplemente se conectará a la base de datos, insertará los mensajes y devolverá los ID. Esa es una operación muy común y debería ser rápida (mysql tiene una especie de puente de Memcache que debería hacer que la operación de la tienda sea aún más rápida y conveniente).

El script de transacción de lectura es igualmente simple, simplemente leerá todos los mensajes con un ID más alto que el que se le pasó y lo devolverá al cliente.

Mantenga estos scripts lo más simples posible y optimice el tiempo de lectura/escritura en la tienda, para que puedan ejecutarse rápidamente e incluso chateando en HTTP simple.

Aún así, su servidor web y la conexión global a Internet pueden no ser lo suficientemente rápidos (aunque hay keep-alive).

Sin embargo, HTTP debería ser lo suficientemente bueno por el momento para probar si su sistema de chat está funcionando realmente sin bucles, ni cliente, ni servidor.

También es bueno mantener los servidores muertos de forma simple, porque cada cliente confía en ellos, por lo que deberían hacer su trabajo y eso es todo.

En cualquier momento puede cambiar el servidor (u ofrecer diferentes tipos de servidores) que pueden interactuar con su cliente de chat al darle al cliente de chat diferentes implementaciones de las funciones de envío y recepción. P.ej. Veo en su pregunta que está usando un cometa, esto debería funcionar también, probablemente sea fácil implementar directamente el servidor para el cometa.

Si en el futuro los websockets son más accesibles (lo que podría no ser el caso debido a consideraciones de seguridad), también puede ofrecer otro tipo de servidor para websockets. Siempre que la estructura de datos de la transmisión esté intacta, funcionará con diferentes tipos de servidores uno al lado del otro. La base de datos se ocupará de la congruencia.

Espero que esto sea útil.


Así como una nota adicional: HTML5 ofrece algo llamado Stream Updates with Server-Sent Events con un online demo y PHP/JS sources. La característica HTML 5 ya ofrece un objeto de evento en javascript que podría usarse para crear una implementación ejemplar de transporte de cliente de chat.

+1

+1, esta es la única respuesta (hasta ahora) que no solo sugiere un enfoque diferente para el bucle infinito, sino que proporciona información sobre cómo crear un intercambio de mensajes dúplex completo (o emulado) basado en la web. –

+1

+1 solo porque quien escribe tanto? Quiero decir, he leído manifiestos que son más cortos. He tenido viajes más cortos al DMV. He tenido desayunos más cortos con gemelos de 2 años. ¡Bromas aparte, lindos detalles y pensamientos! – iND

2

En primer lugar, pregúntese si es necesario actualizar el chat con frecuencia. ¿Qué tipo de chats estarán sucediendo? ¿Es en tiempo real? Q simpleA? ¿Apoyo técnico? Etc. En todos los casos, excepto en los de chat en tiempo real, será mejor que utilice un diseño basado en JS de larga encuesta, ya que las respuestas instantáneas no son tan importantes. Si se trata de chats en tiempo real, debe considerar un diseño parecido al de Gmail mediante el cual mantiene un XHR abierto y envía los mensajes al cliente a medida que se reciben. Si los recursos de conexión son una preocupación, puede obtenerlos mediante un sondeo largo con un intervalo muy breve (por ejemplo, 5-10 segundos).

5

Escribí una publicación de blog sobre cómo tenía que manejar un problema similar (usando node.js, pero se aplican los principios). http://j-query.blogspot.com/2011/11/strategies-for-scaling-real-time-web.html

Mi sugerencia es, si va a ser grande o bien a) que necesita para almacenar en caché como un loco en su capa de servidor web, lo que probablemente significa que su llamada AJAX tiene que tener una marca de tiempo en ella, o b) usar algo como socket.io, que está diseñado para escalar aplicaciones web en tiempo real y tiene soporte integrado para canales.

5

Infinite loops en php puede y usará el 100% de su CPU. Las funciones de sueño solucionarán ese problema. Sin embargo, es probable que no desee tener un proceso HTTP por separado que se ejecute todo el tiempo para cada cliente que esté conectado a su servidor porque se le acabarán las conexiones. Simplemente podría tener un proceso de php que examine todos los mensajes entrantes y los dirija a la persona adecuada a medida que ingresen. Este proceso podría iniciarse desde un trabajo de cron una vez por minuto. He escrito este tipo de cosas muchas veces y funciona a las mil maravillas. Nota: asegúrese de no ejecutar el proceso si ya se está ejecutando o se encontrará con problemas de multiprocesamiento (como recibir mensajes dobles). En otras palabras, debe hacer que el proceso sea seguro.

Si desea chatear en tiempo real, entonces es posible que desee echar un vistazo a StreamHub que abre una conexión dúplex completa al navegador del cliente.

+0

Esta es la respuesta correcta si insiste en usar PHP. PHP no fue diseñado para ser un servidor de chat, así que deberías considerar otras soluciones como Node.js. Sin embargo, PHP es genial para hacer sitios web. –

5

Ahora no es una tarea de PHP o jQuery. Node.js! Hay socket.io, lo que significa WebSockets.

Explicaré por qué node.js es mejor. Tengo una tarea para actualizar los marcadores en la página cada, por ejemplo, 10 segundos. Lo hice con el primer método. Cuando el número de usuarios persistentes llega a 200. Http server and php estaban en problemas. Hubo muchas solicitudes que no fueron necesarias.

Cuál es usted Node.js dan:

  • Creación de habitaciones separadas para los chats (here)
  • enviar datos, sólo para aquellos que tiene actualizaciones (por ejemplo, si yo no tengo ningún mensaje nuevo mi refrescar será bloqueado cuando no habrá selección de base de datos)
  • ejecuta 1 consulta a la base de datos por 0,5 en segundo lugar, no importa la cantidad de usuarios que hay

Ver en Node.j s y Socket.io. Esta solución me ayuda con un gran impulso.

Cuestiones relacionadas