J'ai une page Web qui montre une grande quantité de données provenant du serveur. La communication se fait via ajax.
Chaque fois que l'utilisateur interagit et modifie ces données (disons que l'utilisateur A renomme quelque chose), il dit au serveur de faire l'action et le serveur renvoie les nouvelles données modifiées.
Si l'utilisateur B accède à la page en même temps et crée un nouvel objet de données, il le dira à nouveau au serveur via ajax et le serveur reviendra avec le nouvel objet pour l'utilisateur.
Sur la page de A, nous avons les données avec un objet renommé. Et sur la page de B, nous avons les données avec un nouvel objet. Sur le serveur, les données ont à la fois un objet renommé et un nouvel objet.
Quelles sont mes options pour garder la page synchronisée avec le serveur lorsque plusieurs utilisateurs l'utilisent simultanément?
Des options telles que le verrouillage de la page entière ou le vidage de l'état entier à l'utilisateur à chaque changement sont plutôt évitées.
Si cela aide, dans cet exemple spécifique, la page Web appelle une méthode Web statique qui exécute une procédure stockée sur la base de données. La procédure stockée renverra toutes les données qu'elle a modifiées et pas plus. La méthode Web statique transmet ensuite le retour de la procédure stockée au client.
Bounty Edit:
Comment concevez-vous une application Web multi-utilisateurs qui utilise Ajax pour communiquer avec le serveur mais évite les problèmes de concurrence?
C'est à dire. accès simultané aux fonctionnalités et aux données d'une base de données sans risque de corruption des données ou de l'état
Présentation:
Salut Raynos,
Je ne discuterai aucun produit particulier ici. Ce que d'autres ont mentionné est un bon ensemble d'outils à consulter déjà (peut-être ajouter node.js à cette liste).
D'un point de vue architectural, vous semblez avoir le même problème qui peut être vu dans le logiciel de contrôle de version. Un utilisateur enregistre une modification d'un objet, un autre utilisateur souhaite modifier le même objet d'une autre manière => conflit. Vous devez intégrer les modifications des utilisateurs aux objets tout en étant en mesure de fournir des mises à jour en temps opportun et efficacement, en détectant et en résolvant les conflits comme celui ci-dessus.
Si j'étais à votre place, je développerais quelque chose comme ça:
Déterminez un niveau raisonnable auquel vous définiriez ce que j'appellerais des "artefacts atomiques" (la page? Objets sur la page? Valeurs à l'intérieur des objets?). Cela dépendra de vos serveurs Web, de la base de données et du matériel de mise en cache, du nombre d'utilisateurs, du nombre d'objets, etc. Pas une décision facile à prendre.
Pour chaque artefact atomique:
Un serveur ou un composant de pseudo-serveur capable de fournir efficacement les pertinents changelogs à un utilisateur connecté. Observer-Pattern est votre ami pour cela.
Un client javascript qui peut avoir une connexion HTTP longue durée avec ledit serveur ci-dessus, ou utilise une interrogation légère.
Un composant de mise à jour d'artefacts javascript qui actualise le contenu des sites lorsque le client javascript connecté notifie les modifications de l'historique des artefacts surveillés. (encore une fois, un modèle d'observation pourrait être un bon choix)
Un composant javascript d'artefact-committer qui peut demander de changer un artefact atomique, essayant d'acquérir un verrou mutex. Il détectera si l'état de l'artefact a été modifié par un autre utilisateur quelques secondes auparavant (latence du client javascript et des facteurs de processus de validation) en comparant l'artefact-version-id connu côté client et l'actuel id-version-artefact côté serveur.
Un solutionneur de conflits javascript permettant une décision humaine qui change est la bonne décision. Vous ne voudrez peut-être pas simplement dire à l'utilisateur "Quelqu'un a été plus rapide que vous. J'ai supprimé votre modification. Allez pleurer.". De nombreuses options de différences plutôt techniques ou de solutions plus conviviales semblent possibles.
Alors, comment ça roulerait ...
J'espère que cela peut être un début pour vos propres idées. Je suis sûr qu'il y a beaucoup plus de possibilités. Je suis plus que satisfait de toute critique ou amélioration de ce message, le wiki est activé.
Christoph Strasen
Je sais que c'est une vieille question, mais je pensais que j'allais juste sonner.
OT (transformations opérationnelles) semble être un bon ajustement pour vos besoins en matière d'édition multi-utilisateurs simultanée et cohérente. C'est une technique utilisée dans Google Docs (et a également été utilisée dans Google Wave):
Il existe une bibliothèque basée sur JS pour utiliser les transformations opérationnelles - ShareJS ( http://sharejs.org/ ), écrite par un membre de l'équipe Google Wave.
Et si vous le souhaitez, il existe un framework Web MVC complet - DerbyJS ( http://derbyjs.com/ ) construit sur ShareJS qui fait tout pour vous.
Il utilise BrowserChannel pour la communication entre le serveur et les clients (et je pense que le support WebSockets devrait être en cours - il était là auparavant via Socket.IO, mais a été retiré en raison des problèmes du développeur avec Socket.io) Les documents pour débutants sont un peu clairsemée pour le moment, cependant.
J'envisagerais d'ajouter un tampon modifié en fonction du temps pour chaque ensemble de données. Donc, si vous mettez à jour des tables db, vous devez modifier l'horodatage modifié en conséquence. En utilisant AJAX, vous pouvez comparer l'horodatage modifié du client avec l'horodatage de la source de données - si l'utilisateur est jamais derrière, mettez à jour l'affichage. Similaire à la façon dont ce site vérifie périodiquement une question pour voir si quelqu'un d'autre a répondu pendant que vous tapez une réponse.
Vous devez utiliser des techniques Push (également connues sous le nom de Comet ou Ajax inversé) pour propager les modifications à l'utilisateur dès qu'elles sont apportées à la base de données. La meilleure technique actuellement disponible pour cela semble être l'interrogation longue Ajax, mais elle n'est pas prise en charge par tous les navigateurs, vous avez donc besoin de solutions de rechange. Heureusement, il existe déjà des solutions qui gèrent cela pour vous. Parmi eux se trouvent: orbited.org et le socket.io déjà mentionné.
À l'avenir, il y aura un moyen plus facile de le faire qui s'appelle WebSockets, mais on ne sait pas encore quand cette norme sera prête pour les heures de grande écoute, car il existe des problèmes de sécurité concernant l'état actuel de la norme.
Il ne devrait pas y avoir de problèmes de concurrence dans la base de données avec de nouveaux objets. Mais lorsqu'un utilisateur modifie un objet, le serveur doit disposer d'une logique qui vérifie si l'objet a été modifié ou supprimé entre-temps. Si l'objet a été supprimé, la solution est, encore une fois, simple: jetez simplement la modification.
Mais le problème le plus difficile apparaît lorsque plusieurs utilisateurs modifient le même objet en même temps. Si les utilisateurs 1 et 2 commencent à modifier un objet en même temps, ils effectueront tous les deux leurs modifications sur les mêmes données. Supposons que les modifications apportées par l'utilisateur 1 soient d'abord envoyées au serveur pendant que l'utilisateur 2 modifie toujours les données. Vous avez alors deux options: vous pouvez essayer de fusionner les modifications de l'utilisateur 1 dans les données de l'utilisateur 2 ou vous pouvez dire à l'utilisateur 2 que ses données sont obsolètes et lui afficher un message d'erreur dès que ses données sont envoyées au serveur. Cette dernière option n'est pas très conviviale ici, mais la première est très difficile à mettre en œuvre.
EtherPad , l'une des rares implémentations qui a vraiment réussi à faire les choses pour la première fois, a été acquise par Google. Je pense qu'ils ont ensuite utilisé certaines des technologies d'EtherPad dans Google Docs et Google Wave, mais je ne peux pas le dire avec certitude. Google a également ouvert EtherPad, donc cela vaut peut-être le coup d'œil, selon ce que vous essayez de faire.
Ce n'est vraiment pas facile de faire ce montage simultanément, car il n'est pas possible de faire des opérations atomiques sur le Web en raison de la latence. Peut-être cet article vous aidera à en savoir plus sur le sujet.
Essayer d'écrire tout cela vous-même est un gros travail, et il est très difficile de bien faire les choses. Une option consiste à utiliser un cadre conçu pour maintenir les clients synchronisés avec la base de données et entre eux en temps réel.
J'ai trouvé que le framework Meteor le faisait bien ( http://docs.meteor.com/#reactivity ).
"Meteor adopte le concept de programmation réactive. Cela signifie que vous pouvez écrire votre code dans un style impératif simple, et le résultat sera automatiquement recalculé chaque fois que les données changent dont votre code dépend."
"Ce modèle simple (calcul réactif + source de données réactive) a une large applicabilité. Le programmeur est sauvé de l'écriture des appels de désabonnement/réabonnement et de s'assurer qu'ils sont appelés au bon moment, éliminant des classes entières de code de propagation de données qui autrement bloqueraient votre application avec une logique sujette aux erreurs. "
Je ne peux pas croire que personne n'ait mentionné Meteor . C'est un nouveau cadre immature à coup sûr (et ne prend officiellement en charge qu'une seule base de données), mais il prend tout le travail de grognement et la réflexion d'un multi-utilisateur application comme l'affiche décrit. En fait, vous ne pouvez PAS créer une application de mise à jour en direct multi-utilisateurs. Voici un bref résumé:
Meteor est assez simple pour que je vous suggère au moins d'y jeter un œil pour des idées à voler.
Ces pages Wikipédia peuvent aider à ajouter une perspective à l'apprentissage de concurrence et calcul simultané pour la conception d'un ajaxapplication Web qui soit tire ou est poussé état événement ( EDA ) messages dans un modèle de messagerie . Fondamentalement, les messages sont répliqués vers les abonnés du canal qui répondent aux événements de modification et aux demandes de synchronisation.
Il existe de nombreuses formes de Web simultanées logiciel collaboratif .
Il existe un certain nombre de bibliothèques clientes de l'API HTTP pour etherpad-lite , un éditeur collaboratif en temps réel .
Django-realtime-Playground implémente une application de chat en temps réel dans Django avec diverses technologies en temps réel comme Socket.io .
AppEngine et AppScale implémentent tous deux AppEngine Channel API ; qui est distinct de Google Realtime API , ce qui est démontré par googledrive/realtime-Playground .
Push côté serveur les techniques sont la voie à suivre ici. Comet est (ou était?) Un mot à la mode.
La direction particulière que vous prenez dépend fortement de votre pile de serveurs et de votre flexibilité. Si vous le pouvez, je voudrais jeter un œil à socket.io , qui fournit une implémentation multi-navigateur de websockets, qui fournit un moyen très rationalisé d'avoir une communication bidirectionnelle avec le serveur, permettant au serveur de pousser mises à jour des clients.
En particulier, voir la démonstration this de l'auteur de la bibliothèque, qui illustre presque exactement la situation que vous décrivez.