¿Cómo envía Facebook, Gmail la notificación en tiempo real?

He leído algunas publicaciones sobre este tema y las respuestas son comet, reverse ajax, transmisión http, push de servidor, etc.

¿Cómo funciona la notificación de correo entrante en Gmail?

¿Cómo es posible que GMail Chat pueda realizar solicitudes AJAX sin interacción con el cliente?

Me gustaría saber si hay referencias de código que pueda seguir para escribir un ejemplo muy simple. Muchas publicaciones o sitios web solo hablan de la tecnología. Es difícil encontrar un código de muestra completo. Además, parece que se pueden usar muchos métodos para implementar el cometa, por ejemplo, Hidden IFrame, XMLHttpRequest. En mi opinión, usar XMLHttpRequest es una mejor opción. ¿Qué piensas de los pros y los contras de los diferentes métodos? ¿Cuál usa Gmail?

Sé que debe hacerlo tanto en el servidor como en el lado del cliente. ¿Hay algún código de muestra de PHP y Javascript?

La forma en que Facebook hace esto es bastante interesante.

Un método común de hacer tales notificaciones es sondear una secuencia de comandos en el servidor (usando AJAX) en un intervalo dado (quizás cada pocos segundos), para verificar si algo ha sucedido. Sin embargo, esto puede ser bastante intensivo en la red, y usted a menudo hace solicitudes inútiles, porque nada ha sucedido.

La forma en que Facebook lo hace es usar el enfoque de cometa, en lugar de sondear en un intervalo, tan pronto como finaliza una encuesta, emite otra. Sin embargo, cada solicitud al script en el servidor tiene un tiempo de espera extremadamente largo, y el servidor solo responde a la solicitud una vez que algo ha sucedido. Puede ver que esto suceda si abre la pestaña Consola de Firebug mientras está en Facebook, y las solicitudes de un guión tardan unos minutos. En realidad, es bastante ingenioso, ya que este método reduce inmediatamente el número de solicitudes y la frecuencia con que debe enviarlas. De hecho, ahora tiene un marco de eventos que permite al servidor “desencadenar” eventos.

Detrás de esto, en términos del contenido real devuelto por esas encuestas, se trata de una respuesta JSON, con lo que parece ser una lista de eventos e información sobre ellos. Aunque está minimizado, es un poco difícil de leer.

En términos de la tecnología actual, AJAX es el camino a seguir aquí, ya que puede controlar el tiempo de espera de solicitudes y muchas otras cosas. Yo recomendaría (Cliché de desbordamiento de stack aquí) usando jQuery para hacer el AJAX, se tomarán muchos de los problemas de compatibilidad cruzada. En términos de PHP, ¿podría simplemente sondear una tabla de base de datos de registro de eventos en su script PHP, y solo regresar al cliente cuando ocurra algo? Hay, espero, muchas formas de implementar esto.

Implementar:

Lado del servidor:

Parece haber algunas implementaciones de bibliotecas de cometas en PHP, pero para ser sincero, realmente es muy simple, tal vez algo así como el siguiente pseudocódigo:

while(!has_event_happened()) { sleep(5); } echo json_encode(get_events()); 
  • La función has_event_happened simplemente verificaría si algo hubiera sucedido en una tabla de eventos o algo así, y luego la función get_events devolvería una lista de las nuevas filas en la tabla. Depende del contexto del problema realmente.

  • No olvides cambiar tu tiempo máximo de ejecución de PHP, de lo contrario, ¡se agotará el tiempo de espera!

Lado del cliente:

Eche un vistazo al plugin de jQuery para hacer la interacción de Comet:

Dicho esto, el plugin parece agregar un poco de complejidad, realmente es muy simple en el cliente, quizás (con jQuery) algo así como:

 function doPoll() { $.get("events.php", {}, function(result) { $.each(result.events, function(event) { //iterate over the events //do something with your event }); doPoll(); //this effectively causes the poll to run again as //soon as the response comes back }, 'json'); } $(document).ready(function() { $.ajaxSetup({ timeout: 1000*60//set a global AJAX timeout of a minute }); doPoll(); // do the first poll }); 

Todo depende mucho de cómo se integre su architecture existente.

Actualizar

A medida que sigo recibiendo votaciones al respecto, creo que es razonable recordar que esta respuesta tiene 4 años. La Web ha crecido a un ritmo muy rápido, así que tenga en cuenta esta respuesta.


Recientemente tuve el mismo problema e investigué sobre el tema.

La solución dada se denomina sondeo largo, y para usarla correctamente debe asegurarse de que su solicitud AJAX tenga un tiempo de espera “grande” y de realizar siempre esta solicitud después de que finalice el tiempo actual (tiempo de espera, error o éxito).

Long Polling – Cliente

Aquí, para mantener el código corto, usaré jQuery:

 function pollTask() { $.ajax({ url: '/api/Polling', async: true, // by default, it's async, but... dataType: 'json', // or the dataType you are working with timeout: 10000, // IMPORTANT! this is a 10 seconds timeout cache: false }).done(function (eventList) { // Handle your data here var data; for (var eventName in eventList) { data = eventList[eventName]; dispatcher.handle(eventName, data); // handle the `eventName` with `data` } }).always(pollTask); } 

Es importante recordar eso (de jQuery documentos ):

En jQuery 1.4.xy siguientes, el objeto XMLHttpRequest estará en un estado no válido si la solicitud expira; el acceso a cualquier miembro del objeto puede arrojar una excepción. Solo en Firefox 3.0+, las solicitudes de script y JSONP no se pueden cancelar por un tiempo de espera; la secuencia de comandos se ejecutará incluso si llega después del período de tiempo de espera.

Long Polling – Servidor

No está en ningún idioma específico, pero sería algo como esto:

 function handleRequest () { while (!anythingHappened() || hasTimedOut()) { sleep(2); } return events(); } 

Aquí, hasTimedOut se asegurará de que su código no espere para siempre, y anythingHappened hasTimedOut , hasTimedOut si hasTimedOut algún evento. El sleep es liberar tu hilo para hacer otras cosas mientras nada sucede. Los events devolverán un diccionario de eventos (o cualquier otra estructura de datos que prefiera) en formato JSON (o cualquier otro que prefiera).

Seguramente resuelve el problema, pero si le preocupa la escalabilidad y el rendimiento como lo estaba al investigar, podría considerar otra solución que encontré.

Solución

Use sockets

Del lado del cliente, para evitar problemas de compatibilidad, use socket.io . Intenta usar el socket directamente y tiene errores en otras soluciones cuando los sockets no están disponibles.

Del lado del servidor, cree un servidor usando NodeJS (ejemplo aquí ). El cliente se suscribirá a este canal (observador) creado con el servidor. Cada vez que se debe enviar una notificación, se publica en este canal y se notifica al subscriptor (cliente).

Si no te gusta esta solución, prueba APE ( Ajax Push Engine ).

Espero que haya ayudado.

Según una presentación de diapositivas sobre el sistema de mensajería de Facebook, Facebook usa la tecnología del cometa para “enviar” mensajes a los navegadores web. El servidor de cometas de Facebook se basa en el servidor web mochiweb de fuente abierta Erlang.

En la imagen a continuación, la frase “clusters de canales” significa “servidores de cometas”.

Resumen del sistema

Muchos otros sitios web grandes construyen su propio servidor de cometas, porque existen diferencias entre las necesidades de cada empresa. Pero construir su propio servidor de cometas en un servidor de cometas de código abierto es un buen enfoque.

Puede probar icomet , un servidor de cometas C1000K C ++ construido con libevent. icomet también proporciona una biblioteca de JavaScript, es fácil de usar, tan simple como:

 var comet = new iComet({ sign_url: 'http://' + app_host + '/sign?obj=' + obj, sub_url: 'http://' + icomet_host + '/sub', callback: function(msg){ // on server push alert(msg.content); } }); 

icomet admite una amplia gama de navegadores y sistemas operativos, incluidos Safari (iOS, Mac), IEs (Windows), Firefox, Chrome, etc.

Facebook usa MQTT en lugar de HTTP. El empuje es mejor que el sondeo. A través de HTTP, necesitamos sondear el servidor continuamente, pero a través del servidor MQTT, el mensaje se envía a los clientes.

Comparación entre MQTT y HTTP: http://www.youtube.com/watch?v=-KNPXPmx88E

Nota: mis respuestas son las más adecuadas para dispositivos móviles.

Un problema importante con el sondeo largo es el manejo de errores. Hay dos tipos de errores:

  1. La solicitud podría expirar, en cuyo caso el cliente debería restablecer la conexión de inmediato. Este es un evento normal en largas encuestas cuando no han llegado mensajes.

  2. Un error de red o un error de ejecución. Este es un error real que el cliente debe aceptar graciosamente y esperar a que el servidor vuelva a estar en línea.

El problema principal es que si el controlador de errores restablece la conexión inmediatamente también para un error de tipo 2, los clientes pondrían el servidor en DOS.

Ambas respuestas con código de ejemplo se pierden esto.

 function longPoll() { var shouldDelay = false; $.ajax({ url: 'poll.php', async: true, // by default, it's async, but... dataType: 'json', // or the dataType you are working with timeout: 10000, // IMPORTANT! this is a 10 seconds timeout cache: false }).done(function (data, textStatus, jqXHR) { // do something with data... }).fail(function (jqXHR, textStatus, errorThrown ) { shouldDelay = textStatus !== "timeout"; }).always(function() { // in case of network error. throttle otherwise we DOS ourselves. If it was a timeout, its normal operation. go again. var delay = shouldDelay ? 10000: 0; window.setTimeout(longPoll, delay); }); } longPoll(); //fire first handler 
    Intereting Posts