web-dev-qa-db-fra.com

Pourquoi le sondage est-il accepté dans la programmation Web?

Je travaille actuellement sur un projet Ruby on Rails qui montre une liste d'images.

Un must-have pour ce projet est qu'il affiche les nouveaux messages en temps réel sans avoir besoin de rafraîchir la page Web. Après avoir cherché pendant un certain temps, je suis tombé sur certaines solutions et services JavaScript tels que PubNub; cependant, aucune des solutions proposées n'avait de sens.

Dans la solution JavaScript ( polling ), les événements suivants se produisent:

  • L'utilisateur 1 affiche la liste des photos.
  • En arrière-plan, le code JavaScript interroge un point de terminaison toutes les secondes pour voir s'il y a un nouveau message.
  • L'utilisateur 2 ajoute une nouvelle photo.
  • Il y a un délai de 50 ms avant que le nouveau cycle soit déclenché et récupère les nouvelles données.
  • Le nouveau contenu est chargé dans le DOM .

Cela semble étrange lorsqu'il est traduit dans un exemple réel:

  • L'utilisateur 1 tient une pile de photos sur son bureau.
  • Il se rend chez le photographe à chaque seconde et lui demande s'il en a un nouveau.
  • Le photographe fait une nouvelle photo.
  • Cette seconde, quand il/elle entre, elle peut prendre la photo et la mettre sur la pile.

À mon avis, la solution devrait être la suivante:

  • L'utilisateur 1 tient une pile de photos sur son bureau.
  • Le photographe prend une nouvelle photo.
  • Le photographe marche vers le tas et le met avec le reste.

La solution PubNub est fondamentalement la même, mais cette fois il y a un stagiaire marchant entre les parties pour partager les données.

Inutile de dire que les deux solutions sont très consommatrices d'énergie car elles sont déclenchées même lorsqu'il n'y a pas de données à charger.

Autant que je sache, il n'y a aucune explication (logique) pour laquelle ce mode de mise en œuvre est utilisé dans presque toutes les applications en temps réel.

110
dennis

Pousser fonctionne bien pour 1 ou un nombre limité d'utilisateurs.

Maintenant, changez le scénario avec un photographe et 1000 utilisateurs qui veulent tous une copie de l'image. Le photographe devra marcher jusqu'à 1000 piles. Certains d'entre eux peuvent être dans un bureau verrouillé ou répartis sur le sol. Ou leur utilisateur en vacances, et pas intéressé par de nouvelles photos pour le moment.

Le photographe serait occupé à marcher tout le temps et ne prendrait pas de nouvelles photos.

Fondamentalement: un modèle pull/poll s'adapte mieux à de nombreux lecteurs peu fiables avec des exigences en temps réel lâches (si une image met 10 secondes plus tard pour arriver sur une pile, quel est le problème).

Cela dit, un modèle Push est toujours meilleur dans de nombreuses situations. Si vous avez besoin d'une faible latence (vous avez besoin de cette nouvelle photo 5 secondes après sa prise), ou les mises à jour sont rares et demandent fréquemment et prévisibles (continuez à demander au photographe toutes les 10 secondes lorsqu'il génère une nouvelle photo par jour), alors tirer n'est pas approprié. Cela dépend de ce que vous essayez de faire. NASDAQ: Poussez. Service météo: tirer. Photographe de mariage: tirez probablement. Agence photo d'actualité: probablement Push.

180
ptyx

Je suis vraiment surpris qu'une seule personne ait mentionné WebSockets . Le support est implémenté dans pratiquement tous les principaux navigateurs .

En fait, PubNub les utilise. Pour votre application, le navigateur s'abonnerait probablement à une prise qui serait diffusée chaque fois qu'une nouvelle photo est disponible. La prise n'enverrait pas la photo, attention, mais juste un lien pour que le navigateur puisse la télécharger de manière asynchrone.

Dans votre exemple, imaginez quelque chose comme:

  1. Le (s) utilisateur (s) fait savoir au photographe qu'il souhaite connaître toutes les futures photos
  2. Le photographe annonce par haut-parleur qu'une nouvelle photo est disponible
  3. L'utilisateur demande une photo au photographe

C'est un peu comme votre exemple de solution d'origine. C'est plus efficace que l'interrogation car le client n'a pas à envoyer de données au serveur (sauf peut-être battements de cœur .)

De plus, comme d'autres l'ont mentionné, il existe d'autres méthodes qui sont meilleures que la simple interrogation et qui fonctionnent dans les anciens navigateurs ( longpolling, et al .)

106
korylprince

Parfois, assez bon est assez bon.

De toutes les manières possibles de mettre en œuvre un processus de communication "en temps réel", l'interrogation est peut-être la manière la plus simple. L'interrogation peut être utilisée efficacement lorsque l'intervalle d'interrogation est relativement long (c'est-à-dire secondes, minutes ou heures plutôt qu'instantané), et les cycles d'horloge consommés en vérifiant la connexion ou la ressource n'ont pas vraiment d'importance.

42
Robert Harvey

Le protocole HTTP est limité en ce que le client DOIT être celui qui lance la demande. Le serveur ne peut pas communiquer avec le client à moins de répondre à la demande d'un client.

Donc, pour ajuster votre exemple du monde réel, ajoutez la retenue suivante:

  • L'utilisateur 2 peut SEULEMENT répondre aux questions de l'utilisateur 1 avec une réponse en une seule phrase, après quoi l'utilisateur 1 doit partir. L'utilisateur 2 n'a pas d'autre moyen de communiquer.

Avec cette nouvelle retenue, comment feriez-vous autre chose que le vote?

31
riwalk

Pourquoi le vote est-il accepté? Parce qu'en réalité, chaque solution est en fait un sondage de bas niveau!

Si le serveur doit vous mettre à jour dès que de nouvelles images sont disponibles, il doit généralement avoir une connexion avec vous - car les adresses IP changent souvent et vous ne savez jamais si quelqu'un n'est plus intéressé, donc le client doit envoyer une forme de signal de maintien en vie, par exemple, "Je suis toujours là, je ne suis pas hors ligne"

Toutes les connexions avec état (par exemple, TCP/IP) fonctionnent de la même manière, car vous ne pouvez envoyer que des paquets de données uniques sur Internet; on ne sait jamais si l'autre partie est toujours là.

Donc, chaque protocole a un délai d'expiration. Si une entité ne répond pas dans les X secondes, elle est présumée morte. Donc, même si vous ne disposez que d'une connexion ouverte entre le serveur et le client, sans envoyer de données, le serveur et le client doivent envoyer des paquets persistants réguliers (cela est géré à bas niveau si vous ouvrez une connexion entre eux) - et comment cela en fin de compte différent du sondage?

Donc, la meilleure approche serait probablement longue:

Le client envoie une demande immédiatement après le chargement du site (par exemple, en disant au photographe "Dites-moi s'il y a de nouvelles photos"), mais le serveur ne répond pas s'il n'y a pas de nouvelles photos. Dès que la demande expire, le client demande à nouveau.

Si le serveur a maintenant de nouvelles images, il peut immédiatement répondre à tous les clients qui font la queue pour de nouvelles images. Ainsi, votre temps de réaction après une nouvelle image est encore plus court qu'avec Push, car le client attend toujours une connexion ouverte pour une réponse et vous n'avez pas besoin d'établir une connexion avec le client. Et les requêtes d'interrogation du client ne sont pas beaucoup plus de trafic qu'une connexion constante entre le client et le serveur pour une réponse!

13
Falco

L'un des avantages du sondage est qu'il limite les dommages qui peuvent être causés si un message est manquant ou si l'état de quelque chose est perturbé. Si X demande à Y son état une fois toutes les cinq secondes, la perte d'une demande ou d'une réponse entraînera simplement une mise à jour des informations de X au lieu de 5. Si Y est redémarré, X pourra le découvrir la prochaine fois. moment où Y est capable de répondre à l'un des messages de X. Si X est redémarré, cela ne devrait jamais vous déranger de demander quoi que ce soit à Y par la suite, mais quiconque observe le statut de X devrait reconnaître qu'il a été redémarré.

Si au lieu de X interroger Y, X s'est appuyé sur Y pour l'informer chaque fois que son état a changé, alors si l'état de Y a changé et qu'il a envoyé un message à X, mais pour une raison quelconque, ce message n'a pas été reçu, X peut ne jamais prendre connaissance du changement . De même, si Y est redémarré et n'a aucune raison d'envoyer à X un message sur quoi que ce soit.

Dans certains cas, il peut être utile pour X de demander à Y d'envoyer de manière autonome des messages avec son statut, soit périodiquement soit lorsqu'il change, et de ne demander à X que si cela dure trop longtemps sans entendre quoi que ce soit de Y. Une telle conception peut éliminer le besoin pour X d'envoyer la plupart de ses messages (généralement, X devrait au moins occasionnellement informer Y qu'il est toujours intéressé à recevoir des messages, et Y devrait cesser d'envoyer des messages si cela va trop longtemps sans aucune indication d'intérêt). Une telle conception nécessiterait cependant que Y de manière persistante conserve les informations sur X, plutôt que de pouvoir simplement envoyer une réponse à celui qui l'a interrogé et d'oublier immédiatement qui c'était. Si Y est un système embarqué, une telle simplification peut aider à réduire suffisamment les besoins en mémoire pour permettre l'utilisation d'un contrôleur plus petit et moins cher.

L'interrogation peut avoir un avantage supplémentaire lors de l'utilisation d'un support de communication potentiellement peu fiable (par exemple UDP ou radio): elle peut largement éliminer le besoin d'accusé de réception de couche liaison. Si X envoie à Y une demande d'état Q, Y répond avec un rapport d'état R et X entend R, X n'aura pas besoin d'entendre d'accusé de réception de couche liaison pour que Q sache qu'il a été reçu. Inversement, une fois que Y envoie R, il n'a pas besoin de savoir ou de se soucier si X l'a reçu. Si X envoie une demande d'état et n'obtient aucune réponse, il peut en envoyer une autre. Si Y envoie un rapport et que X ne l'entend pas, X enverra une autre demande. Si chaque demande sort une fois et donne une réponse ou non, aucune des parties n'a besoin de savoir ou de se soucier si un message particulier a été reçu. Étant donné que l'envoi d'un accusé de réception peut consommer presque autant de bande passante qu'une demande ou un rapport d'état, l'utilisation d'un aller-retour de rapport de demande ne coûte pas beaucoup plus cher qu'un rapport et un accusé de réception non sollicités. Si X envoie quelques demandes sans obtenir de réponses, il peut, sur certains réseaux à routage dynamique, avoir besoin d'activer les accusés de réception de niveau lien (et demander dans sa demande que Y fasse de même) afin que la pile de protocoles sous-jacente puisse reconnaître le problème de livraison et rechercher une nouvelle route, mais quand les choses fonctionnent, un modèle de rapport de demande sera plus efficace que d'utiliser des accusés de réception au niveau du lien.

9
supercat

Pour une raison quelconque, ces jours-ci, tous les jeunes développeurs Web semblent avoir oublié les leçons du passé et pourquoi certaines choses ont évolué comme elles l'ont fait.

  1. La bande passante était un problème
  2. La connexion peut être intermittente.
  3. Les navigateurs n'avaient pas autant de puissance de calcul
  4. Il existe d'autres méthodes d'accès au contenu. Le web n'est pas w3.

Face à ces contraintes, vous pourriez ne pas avoir une communication bidirectionnelle constante. Et si vous examiniez le modèle OSI, vous constateriez que la plupart des considérations visent à dissocier la persistance de la connexion sous-jacente.

Dans cet esprit, une méthode d'interrogation pour extraire des informations est un excellent moyen de réduire la bande passante et le calcul côté client. L'essor de Push est en grande partie dû au fait que le client effectue une interrogation constante ou des sockets Web. Personnellement, si j'étais tout le monde là-bas, j'apprécierais la régularité des sondages comme moyen d'analyse du trafic, où une demande GET/POST hors du temps signalerait un homme dans la situation intermédiaire d'une certaine sorte.

1
guestaccount

La question est d'équilibrer le nombre de sondages inutiles par rapport au nombre de poussées inutiles.

Si vous sondez:

  • Vous obtenez une réponse en ce moment même. Bien si vous ne le demandez qu'occasionnellement ou si vous avez besoin d'un ensemble de données en ce moment même.
  • Vous pourriez obtenir une réponse "sans contenu", provoquant une charge inutile sur la ligne.
  • Vous mettez la charge sur la ligne uniquement lorsque vous interrogez, mais toujours lorsque vous interrogez.

Si vous poussez:

  • Vous livrez la réponse dès qu'elle est disponible, ce qui permet un traitement immédiat côté client.
  • Vous pouvez fournir des données à des clients qui ne sont pas intéressés par ces données, provoquant une charge inutile sur la ligne.
  • Vous mettez une charge sur la ligne chaque fois qu'il y a de nouvelles données, mais uniquement lorsqu'il y a de nouvelles données.

Il existe plusieurs solutions sur la façon de gérer les différents scénarios et leurs inconvénients, comme par exemple un temps minimum entre les sondages, des procurations de sondage uniquement pour retirer la charge du système principal, ou - pour les push - un règlement pour enregistrer et spécifier les données souhaitées suivies de la désinscription à la déconnexion. Lequel convient le mieux n'est rien que vous puissiez dire en général, cela dépend du système.

Dans votre exemple, l'interrogation n'est pas la solution la plus efficace, mais la plus pratique. Il est très facile d'écrire un système d'interrogation en JavaScript, et il est également très facile de l'implémenter côté livraison. Un serveur conçu pour fournir des données d'image devrait être capable de gérer les demandes supplémentaires, et sinon, il peut être mis à l'échelle de façon linéaire, car les données sont principalement statiques et peuvent donc être facilement mises en cache.

Une méthode Push implémentant une connexion, une description des données souhaitées et enfin une déconnexion serait la plus efficace, mais est probablement trop complexe pour le "script-kiddy" moyen, et doit traiter la question: et si l'utilisateur ferme simplement le navigateur et la déconnexion ne peut pas être effectuée?

Peut-être qu'il vaut mieux avoir plus d'utilisateurs (car l'accès est facile) que d'économiser quelques dollars sur un autre cache-serveur?

1
TwoThe