274 votes

Comment facebook, gmail envoient-ils la notification en temps réel ?

J'ai lu quelques messages à ce sujet et les réponses sont comet, reverse ajax, http streaming, server push, etc.

Comment fonctionne la notification du courrier entrant sur Gmail ?

Comment GMail Chat est-il capable d'effectuer des requêtes AJAX sans interaction avec le client ?

Je voudrais savoir s'il existe des références de code que je peux suivre pour écrire un exemple très simple. De nombreux articles ou sites Web ne font que parler de la technologie. Il est difficile de trouver un exemple de code complet. Par ailleurs, il semble que de nombreuses méthodes puissent être utilisées pour mettre en œuvre la comète, par exemple Hidden IFrame, XMLHttpRequest. À mon avis, l'utilisation de XMLHttpRequest est un meilleur choix. Que pensez-vous des avantages et des inconvénients des différentes méthodes ? Laquelle Gmail utilise-t-il ?

Je sais qu'il faut le faire à la fois du côté serveur et du côté client. Existe-t-il des exemples de code PHP et Javascript ?

436voto

Kazar Points 16014

La façon dont Facebook procède est assez intéressante.

Une méthode courante pour effectuer ces notifications consiste à interroger un script sur le serveur (en utilisant AJAX) à un intervalle donné (peut-être toutes les quelques secondes), pour vérifier si quelque chose s'est produit. Cependant, cela peut être assez gourmand en réseau, et vous faites souvent des demandes inutiles, car rien ne s'est passé.

La façon dont Facebook le fait est d'utiliser l'approche de la comète, plutôt que de sonder sur un intervalle, dès qu'un sondage se termine, il en émet un autre. Cependant, chaque demande au script sur le serveur a un délai d'attente extrêmement long, et le serveur ne répond à la demande que lorsque quelque chose s'est produit. Vous pouvez voir ce qui se passe si vous affichez l'onglet Console de Firebug lorsque vous êtes sur Facebook, les demandes à un script pouvant prendre plusieurs minutes. C'est vraiment ingénieux, car cette méthode réduit immédiatement le nombre de requêtes et la fréquence à laquelle vous devez les envoyer. Vous disposez désormais d'un cadre événementiel qui permet au serveur de déclencher des événements.

Derrière cela, en termes de contenu réel renvoyé par ces sondages, c'est une réponse JSON, avec ce qui semble être une liste d'événements, et des informations à leur sujet. Le contenu est réduit à sa plus simple expression, ce qui le rend un peu difficile à lire.

En ce qui concerne la technologie proprement dite, AJAX est la voie à suivre, car vous pouvez contrôler les délais d'attente des requêtes et bien d'autres choses encore. Je recommanderais (cliché de Stack overflow ici) d'utiliser jQuery pour faire AJAX, cela éliminera beaucoup de problèmes de compatibilité croisée. En termes de PHP, vous pourriez simplement interroger une table de base de données du journal des événements dans votre script PHP, et ne retourner au client que lorsque quelque chose se produit ? Il y a, je pense, de nombreuses façons d'implémenter cela.

Mise en œuvre :

Côté serveur :

Il semble y avoir quelques implémentations des bibliothèques comet en PHP, mais pour être honnête, c'est vraiment très simple, quelque chose comme le pseudocode suivant :

while(!has_event_happened()) {
   sleep(5);
}

echo json_encode(get_events());
  • La fonction has_event_happened vérifierait simplement si quelque chose s'est produit dans une table d'événements ou autre, puis la fonction get_events renverrait une liste des nouvelles lignes de la table ? Tout dépend du contexte du problème.

  • N'oubliez pas de modifier le temps d'exécution maximal de votre PHP, sinon le délai d'attente sera trop court !

Côté client :

Jetez un coup d'œil au plugin jQuery pour l'interaction avec Comet :

Cela dit, le plugin semble ajouter un peu de complexité, il est vraiment très simple sur le client, peut-être (avec jQuery) quelque chose comme :

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
});

Tout cela dépend beaucoup de la manière dont votre architecture existante est constituée.

2 votes

C'est une explication très agréable et détaillée. Je vous remercie. Avez-vous un exemple de code pour l'une des nombreuses façons d'implémenter cela ?

0 votes

Jetez un coup d'œil aux modifications que vous venez d'ajouter, quelques exemples de code source, cela peut vous aider.

0 votes

Bonne explication. Mais, je ne crois pas que PHP soit le bon choix pour le côté serveur. Un cadre et un langage supportant l'asynchronie devraient être utilisés pour avoir une bonne évolutivité.

45voto

Walter Macambira Points 584

Mise à jour

Comme je continue à recevoir des votes positifs à ce sujet, je pense qu'il est raisonnable de rappeler que cette réponse a 4 ans. Le Web s'est développé à un rythme très rapide, alors soyez attentifs à cette réponse.


J'ai eu le même problème récemment et j'ai fait des recherches sur le sujet.

La solution proposée est appelée "long polling", et pour l'utiliser correctement, vous devez vous assurer que votre requête AJAX dispose d'un "large" timeout et de toujours effectuer cette requête après la fin du courant (timeout, erreur ou succès).

Longs scrutins - Client

Ici, pour garder un code court, je vais utiliser 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);

}

Il est important de se rappeler que (de Documentation sur jQuery ) :

Dans les versions jQuery 1.4.x et inférieures, l'objet XMLHttpRequest se trouve dans un état invalide si la requête expire. état invalide si la requête expire ; l'accès à tout membre de l'objet peut peut entraîner une exception. Dans Firefox 3.0+ uniquement, les demandes script et JSONP ne peuvent pas être annulées par un délai d'attente ; le script s'exécutera même s'il arrive après le délai d'attente. il arrive après le délai d'attente.

Interrogation longue durée - Serveur

Ce n'est pas dans une langue spécifique, mais ce serait quelque chose comme ça :

function handleRequest () {  

     while (!anythingHappened() || hasTimedOut()) { sleep(2); }

     return events();

} 

Ici, hasTimedOut s'assurera que votre code n'attende pas indéfiniment, et anythingHappened vérifiera si un événement s'est produit. Le site sleep sert à libérer votre fil pour faire autre chose pendant que rien ne se passe. Le site events retournera un dictionnaire d'événements (ou toute autre structure de données que vous préférez) au format JSON (ou tout autre que vous préférez).

Elle résout sûrement le problème, mais si vous êtes préoccupé par l'évolutivité et la performance comme je l'étais lors de mes recherches, vous pourriez envisager une autre solution que j'ai trouvée.

Solution

Utilisez des douilles !

Du côté client, pour éviter tout problème de compatibilité, utilisez socket.io . Il essaie d'utiliser directement les sockets, et a des solutions de repli vers d'autres solutions lorsque les sockets ne sont pas disponibles.

Du côté serveur, créez un serveur en utilisant NodeJS (exemple aquí ). Le client s'abonne à ce canal (observateur) créé avec le serveur. Chaque fois qu'une notification doit être envoyée, elle est publiée dans ce canal et le souscripteur (client) est notifié.

Si vous n'aimez pas cette solution, essayez APE ( Moteur de poussée Ajax ).

J'espère avoir aidé.

0 votes

Pensez-vous que l'une remplace l'autre ou que les deux technologies sont nécessaires pour un même projet ?

0 votes

Si vous voulez parler d'APE et de NodeJS, vous pouvez choisir l'un d'entre eux. Si vous voulez parler de requêtes AJAX périodiques et de celle que j'ai suggérée, ma solution peut se rabattre sur celle d'AJAX lorsque le support des sockets fait défaut (voir la documentation de socket.io). Dans les deux cas, vous n'avez besoin que d'une seule solution.

0 votes

Hé Walter, j'aimerais utiliser votre suggestion sur l'un de mes sites. Savez-vous où je peux obtenir un serveur de sockets ? Merci !

19voto

ideawu Points 500

Selon un diaporama sur le système de messagerie de Facebook Facebook utilise la technologie comet pour "pousser" les messages vers les navigateurs web. Le serveur comet de Facebook est construit sur le serveur web Erlang open source mochiweb.

Dans l'image ci-dessous, l'expression "amas de canaux" signifie "serveurs de comètes".

System overview

De nombreux autres grands sites web construisent leur propre serveur comet, car il existe des différences entre les besoins de chaque entreprise. Mais construire votre propre serveur comet sur un serveur comet open source est une bonne approche.

Vous pouvez essayer icomet icomet, un serveur de comètes C1000K C++ construit avec libevent. icomet fournit également une bibliothèque JavaScript, il est facile à utiliser comme simple :

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 prend en charge un large éventail de navigateurs et de systèmes d'exploitation, notamment Safari(iOS, Mac), IEs(Windows), Firefox, Chrome, etc.

0 votes

Cette image décrit très bien le scénario. Cela aurait été bien si un exemple concret avait été donné. Par exemple, que se passe-t-il lorsqu'une personne ouvre (initie) un chatbox avec un ami ? Comment facebook se branche sur cette conversation spécifique et envoie des messages aux deux parties ? (juste une supposition : je peux seulement imaginer que le programme d'application ouvre un socket et lie les deux adresses des clients, puis continue à écouter et à écrire chaque fois qu'un message est écrit dans la boîte).

5voto

Walter Caraza Points 496

Vous pouvez utiliser socket.io est mieux que comet

5voto

Abhinav Points 108

Facebook utilise MQTT au lieu de HTTP. Le push est meilleur que le polling. Avec HTTP, nous devons interroger le serveur en permanence, mais avec MQTT, le serveur envoie le message aux clients.

Comparaison entre MQTT et HTTP : http://www.youtube.com/watch?v=-KNPXPmx88E

Remarque : mes réponses sont adaptées aux appareils mobiles.

3 votes

En outre, google utilise le service GCM pour Android, qui peut être utilisé par les développeurs pour mettre en œuvre le service de messages push. developer.Android.com/google/gcm/index.html Veuillez accepter si vous trouvez la réponse utile.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X